使用场景
通常在React应用中,数据的传递是通过props属性从上到下(由父到子)进行传递(不用Redux), 但有时有些数据是非常通用的,比如地区偏好,UI主题,当前认证的用户, 在很多组件中都会使用,此时通过prop属性传递是非常繁琐的,所以React提供了一种在组件间传递数据的方式,而避免通过props属性在每一层的组件树之间显示传递—— Context。
Context API
- React.createContext
const {Provider, Consumer} React.createContext(defaultValue);
- 定义一个Context, 创建一对 { Provider, Consumer }。
- Provider
<Provider value={/* some value */}>
- 收一个 value 属性传递给 Provider 的后代 Consumers.
- 一个Provider可以有多个Consumers。
- Provider可以被嵌套。
- Consumer
<Consumer> {value => /* render something based on the context value */} </Consumer>
- 接收一个 函数作为子节点. 函数接收当前 context 的值并返回一个 React 节点。
- 传递给函数的 value 将等于组件树中上层 context 的最近的 Provider 的 value 属性。
- 如果 context 没有 Provider ,那么 value 参数将等于被传递给 createContext() 的 defaultValue。
典型使用场景
- 动态Context, 切换系统语言
- create LocalContext
export const LocalContext = React.createContext(Constants.enStrings);
- define Provider
class localedProvider extends React.Component { constructor(props) { super(props); this.state = { local: Constants.enStrings, } this.changeLocalLanguage = this.changeLocalLanguage.bind(this); } changeLocalLanguage() { const newLocal = this.state.local === Constants.enStrings ? Constants.cnStrings : Constants.enStrings; this.setState({ local: newLocal, }); } render() { return ( <div className="context-api"> <button className="change-language-button" onClick={this.changeLocalLanguage}> Change Language</button> <LocalContext.Provider value={this.state.local}> {this.props.children} </LocalContext.Provider> </div> ); } } export default localedProvider;
- define Consumer
class LocalConsumer extends React.Component { render() { return ( <LocalContext.Consumer> {local => ( <React.Fragment> <button>{local.submit}</button> <button>{local.cancel}</button> </React.Fragment> )} </LocalContext.Consumer> ) } } export default LocalConsumer;
- use LocalContext
class LocalContextComponent extends React.Component { render() { return ( <LocalProvider> <LocalConsumer/> </LocalProvider> ) } } export default LocalContextComponent;
注意事项
- Consumer组件的使用必须是Provider组件的子组件,否则使用的value一直都是默认值。
- 当 React 渲染 context 组件 Consumer 时,它将从组件树的上层中最接近的匹配的 Provider 读取当前的 context 值.
- refs 不会自动的传递给被封装的元素。为了解决这个问题,使用 React.forwardRef:
- 将Provider中的传递的value, 放在state中,而不是直接传递一个对象, 因为会触发意外的渲染???