hooks: useContext with useState not updating
See original GitHub issueDo you want to request a feature or report a bug?
seems itās a bug. š
What is the current behavior?
Nested context provider and useContext
hooks seems to be conflicting, updates get discarded.
What is the expected behavior?
When connecting to a context, it should update whenever itās value
changes.
Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?
- react:
18.8.0-alpha.1
(also reproduced on16.7.0-alpha.0
) - browser:
chrome 71
- os: macOS Sierra
more details
While working on a cleanup of a localStorage āconnectionā,
I tried to mix 2 articles ([1]
& [2]
) from the official react documentation, Iāve implemented it with hooks, but the value seems not to be passing through.
Iāve put up a streamlined demo on codesandbox [3]
.
The actual implementation is only a couple of lines more (parsing it from and stringifying it to JSON).
Workarounds that I found:
- If I create a new function on each render around the
setValue
function, it actually works.- but this goes against the advice on
[1]
about avoiding creating new values.
- but this goes against the advice on
- Migrate it to a class and use
componentDidUpdate
instead ofuseEffect
.- Iām actually using this right now, as it works. Including saving a reference to the function in the state.
Is there anything that shouldnāt work on the code below? the effect gets triggered with the changes,
but the value doesnāt get updated on the components that consume via hook. see repro code [3]
const createLocalStorage = key => {
const initialValue = localStorage.getItem(key)
const ValueContext = createContext(initialValue)
const SetterContext = createContext(() => {})
const useStorage = () => [ValueContext, SetterContext].map(useContext)
const Provider = ({children}) => {
const [value, setValue] = useState(initialValue)
useEffect(
() => {
console.log('effect', value)
localStorage.setItem(key, value)
},
[value],
)
return (
<ValueContext.Provider value={value}>
<SetterContext.Provider value={setValue}>
{children}
</SetterContext.Provider>
</ValueContext.Provider>
)
}
return [Provider, useStorage]
}
[1]
: https://reactjs.org/docs/hooks-faq.html#how-to-avoid-passing-callbacks-down
[2]
: https://reactjs.org/docs/context.html#updating-context-from-a-nested-component
[3]
: https://codesandbox.io/s/0yzjr8vnrv
Issue Analytics
- State:
- Created 5 years ago
- Reactions:1
- Comments:6 (2 by maintainers)
It looks to me like your
useContext
calls are in the same component as aProvider
. In that sense theyāre reading context above the Provider (the default one).Providerās value only influences context for components inside of it.
By the way, if you didnāt try to cheat the Hooks rules with code like
[A, B].map(useContext)
you might have noticed this sooner šAaah youāre right I misread your example. Yeah
observedBits
is the issue here. Seems like a pitfall, but then we also donāt recommend to ever calluseContext
dynamically soā¦