-
Notifications
You must be signed in to change notification settings - Fork 49.9k
Description
Do you want to request a feature or report a bug?
bug
What is the current behavior?
When different contexts are nested, as in they have different types, they do not unwind correctly when rendering via renderToString().
Here is a snippet that demonstrates the issue:
import React from 'react';
import { renderToString } from 'react-dom/server';
const valueA = { letter: 'A' };
const valueB = { letter: 'B' };
const LetterContext = React.createContext(valueA);
const NumberContext = React.createContext(undefined);
const html = renderToString((
<LetterContext.Provider value={valueA}>
<NumberContext.Provider>
<LetterContext.Consumer>
{letterValue => (
<div>
{letterValue.letter}
<LetterContext.Provider value={valueB}>
<LetterContext.Consumer>
{innerValue => <div>{innerValue.letter}</div>}
</LetterContext.Consumer>
</LetterContext.Provider>
</div>
)}
</LetterContext.Consumer>
<LetterContext.Consumer>
{value => <div>{value.letter}</div>}
</LetterContext.Consumer>
</NumberContext.Provider>
</LetterContext.Provider>
));
console.log(html);
This results in:
value.letter
^
TypeError: Cannot read property 'letter' of undefined
at Object.children (/Users/ericsoderberg/Documents/git/grommet2/grommet-icons-site/tools/example.js:25:31)
at ReactDOMServerRenderer.render (/Users/ericsoderberg/Documents/git/grommet2/grommet-icons-site/node_modules/react-dom/cjs/react-dom-server.node.development.js:2462:55)
at ReactDOMServerRenderer.read (/Users/ericsoderberg/Documents/git/grommet2/grommet-icons-site/node_modules/react-dom/cjs/react-dom-server.node.development.js:2325:19)
at renderToString (/Users/ericsoderberg/Documents/git/grommet2/grommet-icons-site/node_modules/react-dom/cjs/react-dom-server.node.development.js:2697:25)
at Object.<anonymous> (/Users/ericsoderberg/Documents/git/grommet2/grommet-icons-site/tools/example.js:9:14)
at Module._compile (internal/modules/cjs/loader.js:678:30)
at loader (/Users/ericsoderberg/Documents/git/grommet2/grommet-icons-site/node_modules/babel-register/lib/node.js:144:5)
at Object.require.extensions.(anonymous function) [as .js] (/Users/ericsoderberg/Documents/git/grommet2/grommet-icons-site/node_modules/babel-register/lib/node.js:154:7)
at Module.load (internal/modules/cjs/loader.js:589:32)
at tryModuleLoad (internal/modules/cjs/loader.js:528:12)
What is the expected behavior?
When context providers are nested, they should correctly unwind such that the contexts return the correct value at each level. No exception should be generated and the output should be:
<div>A<div>B</div></div><div>A</div>
Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?
This was uncovered using version 16.4.0 of react-dom on OSX using node v10.1.0.
This only shows up when using renderToString(). It works as expected in the browser.
** Note **
I wonder if this might be due to the following snippet of react-dom-server.node.development.js. Where the previous provider added to the stack is assumed to have the same type as the provider being popped.
var context = provider.type._context;
if (this.providerIndex < 0) {
context._currentValue = context._defaultValue;
} else {
// We assume this type is correct because of the index check above.
var previousProvider = this.providerStack[this.providerIndex];
context._currentValue = previousProvider.props.value;
}
I am investigating further and hope to provide a pull request soon.