背景:
react
中,组件之间传递(共享)数据,可以通过全局变量;或者用文件中的局部变量配合export
和import
的形式;但是,如果传递的数据的改变要能造成组件的重新渲染(re-render),上面的方法就行不通了;这时一般我们会用redux
或mobx
这种数据流的方案。
其实react
自己也有应对这种需求的方法:
- 通过
props
自顶而下(top-down
)一层一层的传递 - 通过
Context
第一种方法显然只适合比较简单的场景,层级一旦很多,就很笨重了;而Context
就是来解决这个问题的。
Context provides a way to share values like these between components
without having to explicitly pass a prop through every level of the tree.
Context
提供了一种不需要通过props
一层层的向下传递就能在不同的组件之间共享数据的方法
示例:
- 使用
React.createContext
创建自定义的ThemeContext
Context 可以让我们无须明确地传遍每一个组件,就能将值深入传递进组件树。
“light”为默认值
// ThemeContext.js
const ThemeContext = React.createContext('light');
export default ThemeContext;
- 顶层用
<ThemeContext.Provider>
包裹
每一个自定义的Context对象中都包含一个Provider
组件,在Provider 上有一个value 属性,这个 value 属性将能被订阅了这个context 的后代组件直接获取,这样就可以避免通过props向深层级的组件传递的问题了;并且订阅了context的组件,当context的值放生变化的时候组件会自动重新render
// App.js
import ThemeContext from './ThemeContext.js';
class App extends React.Component {
render() {
// 使用一个 Provider 来将当前的 theme 传递给以下的组件树。
// 无论多深,任何组件都能读取这个值。
// 在这个例子中,我们将 “dark” 作为当前的值传递下去。
// 还可以在这里动态的改变 ThemeContext 的值
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
}
- 中间的组件再也不必指明往下传递 theme 了。
// Toolbar.js
export default function Toolbar(props) {
return (
<div>
<ThemedButton />
</div>
);
}
- 利用
Class.contextType
订阅ThemeContext
内容
将类的static属性contextType
设置为之前创建好的context对象,在当前组件的各生命周期中使用this.context
来访问上下文的内容'dark'
// ThemedButton.js
import ThemeContext from './ThemeContext.js';
class ThemedButton extends React.Component {
// 指定 contextType 读取当前的 theme context。
// React 会往上找到最近的 theme Provider,然后使用它的值。
// 在这个例子中,当前的 theme 值为 “dark”。
static contextType = ThemeContext;
render() {
let theme = this.context;
return <Button theme={theme} />;
}
}
但是函数式组件中,消费 context
就不能使用contextType
了。我们要使用 react 提供的 useContext
api
import React, { useContext } from 'react';
import ThemeContext from './ThemeContext.js';
const ThemedButton = () => {
const {theme} = useContext(ThemeContext)
return <Button theme={theme} />;
}
export default AuthNew;
网友评论