在React中上下文是一种通信方案。
上下文的特点
- 在组件树中,是一种自上而下的单向数据流通信方案,数据只能从父组件注入,在子组件中访问。
- 组件关系只要满足“父组件-后代组件”这种关系时,都可以使用上下文通信。
- 在父组件中provide提供数据,在后代组件中注入并使用,这种通信不具有响应式,有点像vue中的provide/inject通信。
如何使用上下文
-
使用const{Provider,Consumer} = Raact.createContext()get="_blank">创建上下文。
-
使用<Provider value={}></Provider>向组件树中提供数据。
-
在后代组件中使用<Consumer>{(context)=>(jsx/)}</Consumer>访问上下文数据。
- 如果后代组件是类组件,可以使用Page.contextType = ThemeContext访问上下文数据。
使用上下文穿透和上下文通信的区别
- props穿透必须清楚组件之间的关系,上下文只要满足“父组件-后代组件”关系。
- props适合父子关系明显的组件通信,上下文关系适合父子关系不明确的组件通信。
- props穿透会导致后代组件的props变得臃肿,上下文通信更加直接方便。
上下文通信在那些场景遇到
- 路由中会用到上下文通信
- 状态管理中
- 组件库中,切换主题色,切换组件大小等
- 国际化中
使用上下文封装拾色器
import { PureComponent, useState } from "react"
//创建上下文对象
const ThemeContext = React.createContext()
const{Consumer,Provider} = ThemeContext
class App extends PureComponent{
render(){
return(
<Consumer>
{
(context) => {
console.log(context)
return(
<div style={context}>
<h1>555</h1>
</div>
)
}
}
</Consumer>
)
}
}
//封装拾色器
function ThemeToggle({value, onChange}){
const change = (ev) =>{
const key = ev.target.name
// console.log('key',key);
const val = ev.target.value
// console.log('val',val);
//把变化后的主题色回传给父组件
onChange({...value, [key]:val})
}
return(
<>
<div>
<label >前景色</label>
<input type="color" name="color" value={value.color} onChange={change} />
<label >背景色</label>
<input type="color" name="background" value={value.background} onChange={change} />
</div>
</>
)
}
function A(){
const[color ,setColor] = useState({color:'#000000',background:'#000000'})
return(
<Provider value={color}>
<h1>拾色器</h1>
<App />
<ThemeToggle value={color} onChange={ev=>setColor(ev)} />
</Provider>
)
}
export default A