This article is a part of the series "Using cookies in React applications"
How to create a responsive React hook to listen for changes to cookies
This hook now exists as a npm package. See: @blacksheepcode/use-cookie-state
I recently encountered a situation where I have some React code that needs to listen for changes to a cookie, but this cookie logic isn't controlled React.
Some searches reveal tutorial posts like this one that implement a useCookie hook.
This works kind of nicely, we get a nice useState style hook, that also stores into cookies as a side effect, it's helpful for retainining state between sessions.
However, this solution is not responsive to cookie changes that may occur outside of the React context. In fact, two components that were examining the same cookie would not have their updates be observed by the other.
☝️ Interactive demo
Name: John Doe
Age: 30
Server cookie: default-value-for-server-cookie
Click the 'Update User' button and observe the value changes.
Open your browser dev tools.
Observe that when you click 'Update User' a `user-1` cookie is set in the Applications tab.
Observe that when you click 'Server Fetch' an API call is made, and that Response contains a cookie. However our application will not respond to this cookie.
The scenarios where cookies may be set outside of a React context are:
- Cookies being set by HTTP responses
- Cookies being set with JavaScript in your state management layer
We can use the CookieChangeEvent to make a useCookie hook truely responsive.
The CookieStore is not currently supported by Firefox or Safari.
I couldn't a CookieStore polyfill. There is the cookie-store project - but this has not implemented the CookieStore Monitoring Cookies feature. See this issue: https://github.com/markcellus/cookie-store/issues/46
My solution implements the polling solution described in this Stack Overflow answer
Note that on a page refresh the values initially show as 'John Doe' and then cookie value pops in. This is because this blog is has server rendering, and this these solutions access the client cookies. Cookies are available to the server - a solution that avoids this flash is available in this post here.
The a polyfilled implementation of a responsive useCookie looks like this:
Unauthorized. Is your Github token valid?
☝️ Interactive demo
Name: John Doe
Age: 30
Server cookie: default-value-for-server-cookie
Using Chrome observe that our component now responds to cookies set by the api response
Observe that this also works for Firefox. It appears sluggish - this is due the 1000ms poll rate. You can decrease the poll rate for snappier application, this will come at the cost of extra computation for the user.
Questions? Comments? Criticisms? Get in the comments! 👇
Spotted an error? Edit this page with Github