useContext 跟class组件Context是一样的效果,Context能够允许数据跨域组件层级直接传递到任何的子组件身上。
详细请参考: React新特性-Context(一)
系列目录
- React新特性-Context(一)
- React新特性-Lazy和Suspense(二)
- React新特性-memo(三)
- React新特性-Hooks之useState(四)
- React新特性-Hooks之useEffect和useLayoutEffect(五)
- React新特性-Hooks之useContext(六)
- React新特性-Hooks之useRef(七)
- React新特性-Hooks之useMemo和useCallback(八)
- React新特性-Hooks之useReducer(九)
- React新特性-Hooks之自定义Hook(十完结)
如何使用useContext
//Page.js
// Context 可以让我们无须明确地传遍每一个组件,就能将值深入传递进组件树。
import React, { Component } from 'react';
import List from './List'
//导出ThemeContext,让后面的Item组件可以拿到
export const ThemeContext = React.createContext()
export default class Page extends Component {
constructor(props) {
super(props)
this.state = {
theme: 'red'
}
}
onChangeTheme = (color) => {
this.setState({ theme: color })
}
render() {
const data = [
{
id: 1,
text: '随随便便输入',
color: 'yellow'
}, {
id: 2,
text: '随便输入',
color: 'blue'
}
]
// 使用一个 Provider 来将当前的 theme 传递给以下的组件树。
// 无论多深,任何组件都能读取这个value值。
return (
<div>
<ThemeContext.Provider value={{
theme: this.state.theme,
onChangeTheme: this.onChangeTheme
}}>
<List data={data} />
</ThemeContext.Provider >
</div>
)
}
}
// List.js
import React from 'react'
import Item from './Item'
export default function List(props) {
return (
<div> {
props.data.map(i =>
(
<Item
key={i.id}
color={i.color}>
{i.text}
</Item>
))}
</div>
)
}
//Item.js
import React, { useContext } from 'react' //引入useContext
///导入Page中的ThemeContext对象
import { ThemeContext } from './Page'
export default function Item(props) {
//拿到context数据
const context = useContext(ThemeContext)
return (
<div>
<p style={{ color: context.theme }}>
{props.children}
<button onClick={() => context.onChangeTheme(props.color)}>
点击变色
</button>
</p>
<ThemeContext.Consumer>
{value => { console.log(value, 'render') }}
</ThemeContext.Consumer>
</div>
)
}
此示例依照React新特性-Context(一),用useContext
的方式来实现。
跟class组件中的Context有什么不同
Page.js代码中仅仅把创建出的Context对象导出去以供Item组件使用。然后使用useContext
来拿到Context里面的值。
相比较React新特性-Context(一)
的代码大致Page.js和List.js代码都没有变化,只是List改为函数组件。到了Item.js中,改为函数组件,由于函数组件并没有contextType
不能像class组件中这样使用Item.contextType = ThemeContext
,所以引入useContext
函数。利用useContext
的参数传入ThemeContext
对象来拿到Context
的值。
<ThemeContext.Consumer>
{value => { console.log(value, 'render') }}
</ThemeContext.Consumer>
这里ThemeContext.Consumer
的方式一样适用,并未做任何改变。