React: unexpected ContextConsumer or ContextProvider behavior

Created on 8 Feb 2018  路  11Comments  路  Source: facebook/react

Do you want to request a feature or report a bug?
Bug

What is the current behavior?
When use two or more contexts that created by createContext,in the child-tree of cxt2.Provider,i use cxt1.Provider to set a new context of cxt1,i expect only the child consumer got the new cxt1,but the result is that the cxt2.Provider's next sibling's child-tree got an unexpected cxt2.Provider's new context

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem. Your bug will get fixed much faster if we can run your code and it doesn't have dependencies other than React. Paste the link to your JSFiddle (https://jsfiddle.net/Luktwrdm/) or CodeSandbox (https://codesandbox.io/s/new) example below:
createContext issue

What is the expected behavior?
ContextProvider only affect the children node.

Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?
React 16.3.0-alpha.0

Bug

Most helpful comment

Yeah, that's what we were thinking too. Just had to step away for meetings right after writing the test 馃槄 Thanks Brandon!

All 11 comments

Can you create a minimal test case that fails, similar to the ones we have in ReactNewContext-test.internal.js?

In your example, the second UidContext1.Consumer is outside of its provider UidContext1.Provider. I don't think that's a supported use-case to begin with? (I'm not positive.) Although I agree, getting the Context2.Provider value seems unexpected.

I believe this _is_ a valid case and the default value should be passed to the consumer.

I've got this in a test. I'll submit it after lunch.

Added PR #12187 with failing test. Will look into it further soon, but for now this captures the failure.

@bvaughn I took a look, and from what I can tell the problem is related to popProvider:

https://github.com/facebook/react/blob/cbf729659e784792c7b57e8e8a0e88ed6359c604/packages/react-reconciler/src/ReactFiberNewContext.js#L53-L55

previousProviderFiber ends up being the wrong provider (UidContext2), so when context.currentValue is updated to match previousProviderFiber.pendingProps.value it's being updated from the wrong provider.

I _think_ the current stack approach assumes that there's a stable order for providers being pushed and popped from the stack when consumed, but because providers can be nested and consumers can be rendered without providers, it gets out of sync.

Yeah, that's what we were thinking too. Just had to step away for meetings right after writing the test 馃槄 Thanks Brandon!

Awesome! Happy to hear I was on the right track 馃槃 maybe this would be a good problem for some fuzz testing, to cover crazy Provider/Consumer combinations.

Yeah, Andrew's been keen on improving the fuzz tester to better cover cases like this.

Ahh sorry @aweary, I missed that you were looking at this and posted #12190 which might work but I haven't tested it.

@sophiebits no worries at all! I only had enough time to try and diagnose it anyways 馃檪

Was this page helpful?
0 / 5 - 0 ratings