Why is this.context
an empty object, in this React component lifecycle methods?
The context has the correct value in the Consumer
for that context. Only the this.context
API is failing.
const LoremContext = React.createContext({
lorem: "ipsum",
})
class MenuItem extends React.Component {
componentDidMount() {
console.log(
"In MenuItem.componentDidMount, this.context is:",
this.context)
}
render() {
console.log(
"In MenuItem.render, this.context is:",
this.context)
return ( <LoremContext.Consumer>{
(lorem) => {
console.log("In LoremContext.Consumer, lorem is:", lorem)
return (
<li>
{ `Eat ${this.props.dish} at ${lorem}` }
</li>
)
}
}</LoremContext.Consumer> )
}
}
MenuItem.contextType = LoremContext
class Menu extends React.Component {
render() {
…
}
}
class Application extends React.Component {
render() {
return (
<LoremContext.Provider value={ this.props.world.lorem }>
<section className="app">
<Menu menuItems={ [ … ] } />
<p>Fusce varius id arcu egestas sodales</p>
</section>
</LoremContext.Provider>
)
}
ReactDOM.render(
<Application world={ { lorem: "consecteur" } } />,
document.getElementById('app-container'),
)
This is using React 16.4, so it makes use of the documented context API (introduced in React 16.3).
According to that documented API, the above code should get access to the context (defined in the return value from React.createContext
) in two ways:
The LoremContext.Consumer
component receives the context value passed by the LoremContext.Provider
.
The consumer then provides that context value as an argument to the function within that component. In this case, lorem
is the argument that receives the context value.
The this.context
property receives (because of the declared MenuItem.contextType
class property) the context value, inside the “lifecycle methods”.
Only one of those is working for me.
LoremContext.Consumer
API is getting and passing the context value correctly. The console.log
output is: In LoremContext.Consumer, lorem is: consecteur
this.context
is not getting the correct value, instead it gets an empty Object. The console.log
output is: In MenuItem.render, context is: Object { }
In MenuItem.componentDidMount, context is: Object { }
So the consumer is receiving the correct value, but this.context
is not. Why the difference? How can I get the correct value received at this.context
?
Lifecycle of Components Each component in React has a lifecycle which you can monitor and manipulate during its three main phases. The three phases are: Mounting, Updating, and Unmounting.
What is React context? React context allows us to pass down and use (consume) data in whatever component we need in our React app without using props. In other words, React context allows us to share data (state) across our components more easily.
The componentDidUpdate()is called after componentDidMount() and can be useful to perform some action when the state of the component changes. Parameters: Following are the parameter used in this function: prevProps: Previous props passed to the component. prevState: Previous state of the component.
2. How many times componentDidMount is called? React components call componentDidMount only once by default. You can run the component multiple times if you delete the component or change the props or state.
this.context
was introduced in React 16.6 that you see can see here
Before this version, on 16.4, that you are using, accessing context inside React Lifecycles can be achieved:
class Button extends React.Component {
componentDidMount() {
// ThemeContext value is this.props.theme
}
componentDidUpdate(prevProps, prevState) {
// Previous ThemeContext value is prevProps.theme
// New ThemeContext value is this.props.theme
}
render() {
const {theme, children} = this.props;
return (
<button className={theme || 'light'}>
{children}
</button>
);
}
}
export default props => (
<ThemeContext.Consumer>
{theme => <Button {...props} theme={theme} />}
</ThemeContext.Consumer>
);
See docs for more information
Try creating the context in a separate file and then importing it. That worked for me. When createContext
was called in the same file where the <MyContext.Provider>
tag was used, the consumers only saw an empty object. When I moved createContext
to a separate file, the consumers saw the expected values. This applies to both methods of consuming - <MyContext.Consumer>
and MyClass.contextType/this.context
.
I'm afraid I can't explain why this works, but I found the solution in this thread.
Unfortunatelly without this part in the target component it is empty.
static contextType = ThemeContext; // assign the correct context
before created like
const ThemeContext = React.createContext('light');
https://reactjs.org/docs/context.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With