I think there's a bug in 16.7.0-alpha.0 unless this is intentional.
What is the expected behavior?
I've been using the context API to implement a dynamic loader where a parent component is responsible for triggering and loading some network data, and one or more grand-child components want to consume that data or show "Loading..." while that data is being fetched.
What is the current behavior?
When I migrated to useContext() I don't get a re-render, and can't quite see how this is going to come about.
Can you update examples to show dynamic behaviour, or if not supported to highlight that we will still need to use Context.Consumer for that.
It's looking like react-async is a good generalisation of my current approach and also provides a useful view of how they may go with useAsync building on the Hooks API, but it does look even more complex under the hood and perhaps is an API that itself to be at the core of React so as to have good support and coverage.
Can you please provide a code sample demonstrating the bug you're reporting? You can use https://codesandbox.io/s/new as a starting point.
@nealeu Please provide reproducing cases when reporting bugs, that lets us avoid back-and-forth before having a chance to fix them. Thanks.
Sorry folks. If you read what I wrote, you'll see that I am asking if this is the intended behaviour or not. For now I'll leave those with employers who are in profit to take the time on this. I'll just stick with the old ways until things are stable.
That鈥檚 not intentional based on the description. Unfortunately things can only get more stable if people help us by isolating issues. Appreciate your help reporting this and hope we鈥檒l get more details from somebody else!
@nealeu Here's a demo of useContext triggering a rerender even though an ancestor returns false from shouldComponentUpdate:
https://codesandbox.io/s/zw0qk98k9p
For the purposes of updates, it should work exactly the same way as a context Consumer component does.
I'm going to close this issue since I don't believe there is enough info here for this to be actionable for us right now, but if you end up having time to comment here with a small test case or if someone else runs into the same issue we'll definitely take a look.
@nealeu : were you running useContext(MyContext), or useContext(MyContext.Consumer) ? When I tried the latter, I found that my component received an _initial_ value, but did not get re-run when the context updated. The React team has told me that this is actually a bug, in that passing only the consumer shouldn't work at _all_ - you should be passing the _entire_ context object. (Which I still think is a debatable design decision - there's a mismatch in that _rendering_ a consumer by itself works, but calling useContext() with a consumer doesn't.)
@markerikson whoaaaa
@nealeu Can you confirm if this is what you were doing? I'll mention that you should have seen a warning in your console saying this:
Warning: Calling useContext(Context.Consumer) is not supported, may cause bugs, and will be removed in a future major release. Did you mean to call useContext(Context) instead?
But maybe we should make this more obvious.
This is not released yet, it could be better to just never add support to it in useContext to begin with if detectable.
I was using useContext(Context).
I'm happy for this to be closed given there is a working example (thanks @sofiebits), but will have another look as it should come up during our hackathon this week.
@sophiebits Here's a demo of useContext triggering a rerender even though an ancestor returns false from shouldComponentUpdate:
I have a question regarding useContext() as utilized in this demo. I've compared my prototype to this demo and I believe the significant difference of the two is that yours manages a simple type: whereas mine is a composite type: Yours is a simple number type whereas mine is a JSON object containing changes made within. With mine the top level object reference doesn't change. Is this the reason why my children who useContext(DataContext) are not getting notified of changes to the document? I'm looking for best practices here. I've just started researching MobX as a mechanism for observing object fragments within the data for any changes. This may well solve my problem. I see they have released an Alpha of MobX for Hooks just a few days ago. Everything is so cutting edge. That's what I get to play with this weekend.
return
With mine the top level object reference doesn't change. Is this the reason why my children who useContext(DataContext) are not getting notified of changes to the document?
Yes.
https://reactjs.org/docs/context.html#contextprovider
Changes are determined by comparing the new and old values using the same algorithm as
Object.is.
We added a warning for this.
Little offtopic but google directed me here with my slightly different problem, when my function didn't receive context value properly.
My problem was with using useCallback() function and i didn't put the context value into the inputs array of the function, so it was returning memoized version with the default context value.)
For future reference of anyone wondering where the problem is.
const myFunction = useCallback(
(functionInput) => {
// function body
} ,
[inputsArray, contextValue]);
Most helpful comment
That鈥檚 not intentional based on the description. Unfortunately things can only get more stable if people help us by isolating issues. Appreciate your help reporting this and hope we鈥檒l get more details from somebody else!