🪆 Nesting and overriding new React Context API
While learning react-router v4 I read some of their source code. And as we know they are using current context for passing down router and route info overriding previous/parent route info
{% github https://github.com/ReactTraining/react-router %}
getChildContext() {
return {
router: {
...this.context.router,
route: {
location: this.props.location || this.context.router.route.location,
match: this.state.match
}
}
};
}
React team announced new Context API that no longer will be deprecated in React v16.3.0, that is already released :)
https://github.com/facebook/react/releases/tag/v16.3.0
Now I was thinking how ReactTraining will make this overriding using new Context API. From start I used create-react-context polyfill for new context. It works exactly, just change the import.
import { render } from "react-dom";
import React, { createContext } from "react";
// import createContext from "create-react-context";
Next we need to create the context. Context has a Consumer and a Provider
const { Provider, Consumer } = createContext();
Provider is used to pass to him some data in value prop
render() {
return (
<Provider value={"React is Awesome!"}>
nested content...
</Provider>
)
}
And Consumer is used to consume that value using render props
render() {
return (
<Consumer>
{(theValue) => {
return theValue
}}
</Consumer>
// shorthand
<Consumer>
{theValue => theValue}
</Consumer>
)
}
// output
// React is Awesome!
We may use the Consumer how many times we want.
Now back to our overriding. Here is my app
const App = () => (
<Provider value={{ location: "/" }}>
<NestedPath>
<NestedPath location="haha/">
<NestedPath>
<NestedPath>
<NestedPath>
<NestedPath />
</NestedPath>
</NestedPath>
</NestedPath>
</NestedPath>
</NestedPath>
</Provider>
);
ReactDOM.render(<App />, document.getElementById("root"));
And here is the output
/
/location/
/location/haha/
/location/haha/location/
/location/haha/location/location/
/location/haha/location/location/location/
And this is my NestedPath component
const NestedPath = ({ location = "location/", children }) => (
<Consumer>
{(router) => (
<React.Fragment>
<div>{router.location}</div>
<Provider value={{ ...router, location: router.location + location }}>
{children || null}
</Provider>
</React.Fragment>
)}
</Consumer>
);
Here as you see inside Provider we override previous one with a new value. And all child Consumers now will take the new value.
Here is a sandbox to play with
https://codesandbox.io/s/lrvv8w784q
Thanks for reading!!! This is a duplicate of my Medium Story! dev.to is new medium for developers :)
- Created At
- 7/6/2018
- Updated At
- 9/15/2023
- Published At
- 7/6/2018