React16.3 has updated a lot of new content: lifecycle, Context, react.createref (), Portals, and more. With a new, fast front end, we should be used to constantly learning about ╮, ╰, ╭. This article introduces two new combinations of Context and Portals in the official document.
Context
Context provides a way to pass data in a tree of components without manually passing props layer by layer.
In traditional React applications, data is usually passed from parent to child components through layers of props, but this approach can be cumbersome when properties need to be used by many components.
So the Context is designed to share some “global” data in the component tree.
Let’s just look at the example
import React, {Component} from 'react'
const ThemeContext = React.createContext('light')
class App extends Component {
render () {
return( <ThemeContext.Provider value="dark"> <Toolbar /> </ThemeContext.Provider> ) } } function Toolbar () { return ( <div> <ThemeButton /> </div> ) } function ThemeButton (props) { return ( <ThemeContext.Consumer> { theme => <button {... props} theme={theme}>{theme}</button> } </ThemeContext.Consumer> ) }Copy the code
You can see that the ThemeButton gets the theme property directly, without passing props through the Toolbar, which is exactly what the Context does.
New apis appear in the above example: React. CreateContext, Provider, and Consumer. Let me introduce you one by one.
React.createContext
const {Provider, Consumer} = React.createContext(defaultValue);
Copy the code
React. CreateContext creates the {Provider, Consumer} pair of objects. When you use Consumer to fetch data, it matches the nearest corresponding Provider.
DefaultValue is used only when the Consumer does not match the Provider, and the Consumer uses defaultValue.
Provider
<Provider value={/* some value */} >Copy the code
A Provider is a component that allows consumers to subscribe to context changes.
The Provider accepts a value property, and when it changes, its descendant Consumer component receives the changed value accordingly.
Consumer
<Consumer>
{value => /* render something based on the context value */}
</Consumer>
Copy the code
Consumer is a component that subscribes to context changes. It requires passing a function in the node that takes a current context value and returns a React node.
Once the Provider in the parent changes the context value, the Consumer rerenders. If the Consumer parent component shouldComponentUpdate returns false, the Consumer component will still be updated.
The API is pretty neat, so let’s do a final example to reinforce it.
import React, {Component} from 'react'
const ThemeContext = React.createContext({
theme: 'light'.changeTheme: (a)= >{}})class App extends Component {
constructor () {
super(a)this.changeTheme = this.changeTheme.bind(this)
this.state = {
theme: 'light'.changeTheme: this.changeTheme
}
}
changeTheme () {
this.setState({
theme: 'dark'
})
}
render () {
return( <ThemeContext.Provider value={this.state}> <Toolbar /> </ThemeContext.Provider> ) } } function Toolbar () { return ( <div> <ThemeButton /> </div> ) } function ThemeButton (props) { return ( <ThemeContext.Consumer> { ({theme, changeTheme}) => <button {... props} onClick={changeTheme}>{theme}</button> } </ThemeContext.Consumer> ) }Copy the code
Portals
Portals provide a way to render a component’s child elements under other Dom nodes
ReactDOM.createPortal(child, container)
Copy the code
The first parameter is the renderable React element, and the second parameter is the node under it to render.
import React, {Component} from 'react'
import ReactDOM from 'react-dom';
function App () {
return (
<div>
<Modal>
{[1, 2, 3, 4]}
</Modal>
</div>)}class Modal extends Component {
constructor(props) {
super(props);
this.el = document.createElement('div');
}
componentDidMount() {
document.body.appendChild(this.el)
}
componentWillUnmount() {
document.body.removeChild(this.el)
}
render() {
return ReactDOM.createPortal(
this.props.children,
this.el,
)
}
}
Copy the code
In the example above, the contents of the array will be rendered to a div under Document. body, not to the div rendered by the App. This enables the ability to render elements under other DOM nodes.
The thing to notice here is that Modal events still bubble through elements in your App, not directly to the body.
conclusion
This article introduces two new apis: Context and Portals. Both are relatively simple to use, but it’s up to the project application to find best practices.