Do 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?
18.8.0-alpha.1
(also reproduced on 16.7.0-alpha.0
)chrome 71
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:
setValue
function, it actually works.[1]
about avoiding creating new values.componentDidUpdate
instead of useEffect
.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
I've put up a streamlined demo on codesandbox [3].
It looks to me like your useContext
calls are in the same component as a Provider
. 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 ;-)
hey Dan! thanks for the quick response (: just fixed it for me.
btw: useContext
(via useStorage
) is inside App
, which _is_ inside of Provider
in the ReactDOM.render
function. (maybe I made the example too short to see this nesting).
solution:
I just solved it by modifying that quirky .map
line: I missed the observedBits
parameter, that ended up being passed on I've read about it here in the Issues/PRs, but forgot about it when implementing, and ended up messing with the behaviour.
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 call useContext
dynamically so..
Most helpful comment
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 ;-)