React 跨层组件树传值-context上下文
跨层组件树传值,可以使用context上下文来处理,先要定义一个上下文,然后在子孙组件中进行消费
详细文档查看React官网
创建context
首先需要创建一个context,可以给定一个默认值,当消费组件上没有Provider的时候,使用默认值。
然后通过上面的Provider指定想要传递的数据
colorCtx.js
import { createContext } from 'react'
export const ColorCtx = createContext("red")
然后通过CTX.Provider 组件,绑定一个value,用来传递给子孙组件,这里我我们绑定一个{color: 'green'}状态
import React from 'react'
import Child from './Child'
import { ColorCtx } from './context'
class Parent extends React.Component {
constructor(...props) {
super(...props)
this.state = {
color: 'green'
}
}
render() {
return <>
<ColorCtx.Provider value={this.state.color}>
<p>Parent</p>
<Child></Child>
</ColorCtx.Provider>
</>
}
}
export default Parent
消费context
下面我们就可以在子孙组件里面消费绑定的value了,有以下几种方式可以消费
使用
consumer消费在使用
consumer的时候,不能在生命周期中获取到上下文的信息,只能在consumer里面获取到,同时如果需要同时消费多个Provider,也只能使用consumer消费import React from 'react' import { ColorCtx } from './context' class Child extends React.Component { constructor(...props) { super(...props) } render() { return <> <ColorCtx.Consumer> {value => <div> <p style={{color: value}}>Child</p> </div>} </ColorCtx.Consumer> </> } } export default Child使用静态方法
contentType消费通过指定
contentType,来消费Provider,取值的时候就可以使用this.context取值import React from 'react' import { ColorCtx } from './context' class Child extends React.Component { constructor(...props) { super(...props) this.state = { color: 'green' } } // 定义了这个,会把this.context 映射到 vlue static contextType = ColorCtx render() { return <> <div> <p style={{color: this.context}}>Child</p> </div> </> } } //上面的 static contextType = ColorCtx 也可以使用这种方法指定 // Child.contextType = ColorCtx export default Child消费多个
Provider- 创建多个context
import {createContext} from 'react' export const ColorCtx = createContext('red') export const BackColorCtx = createContext('white')- 在父组件中提供多个
Provider
import React from 'react' import Child from './Child' import { ColorCtx, BackColorCtx } from './context' class Parent extends React.Component { constructor(...props) { super(...props) this.state = { color: 'green', backColor: 'black' } } render() { return <> <ColorCtx.Provider value={this.state.color}> <BackColorCtx.Provider value={this.state.backColor}> <p>Parent</p> <Child></Child> </BackColorCtx.Provider> </ColorCtx.Provider> </> } } export default Parent- 在子孙组件中进行消费
import React from 'react' import { ColorCtx, BackColorCtx } from './context' class Child extends React.Component { constructor(...props) { super(...props) } render() { return <> <ColorCtx.Consumer> { color => <BackColorCtx.Consumer> { backColor => <div> <p style={{color: color, backgroundColor: backColor}}>Child</p> </div> } </BackColorCtx.Consumer> } </ColorCtx.Consumer> </> } } export default Child
default默认值
如果说子孙组件没有提供Provider,则子组件的消费者的value会被赋予默认值。
例如第二个子组件Child没有提供Provider,则Child会被渲染成红色,就是上面export const ColorCtx = createContext('red')指定的
class Parent extends React.Component {
constructor(...props) {
super(...props)
this.state = {
color: 'green',
backColor: 'black'
}
}
render() {
return <>
<ColorCtx.Provider value={this.state.color}>
<p>Parent</p>
<Child></Child>
</ColorCtx.Provider>
<Child></Child>
</>
}
}
注意点
当context的value发生变化的时候,会引发子组件的更新,在React内部,很暴力,直接使用===进行对比新旧值,那如果我们使用类似<ColorCtx.Provider value={{someValue: 'value'}}>的方式传递value,内部比较直接{someValue: 'value'} === {someValue: 'value'},此时永远都是false,子组件就会更新,造成性能问题,我们的解决方法是把value放到state中,传递的是state里的值,就像上述例子里那样,这样的话,值没变子组件就不会更新了。
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 289211569@qq.com