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