Nesting and overriding new React Context API

July 10, 2018 0 Comments

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

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 :)

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

Thanks for reading!!! This is a duplicate of my Medium Story! is new medium for developers :)

Tag cloud