非父子组件通信
非父子组件数据的共享
- 在开发中,比较常见的数据传递方式是通过props属性自上而下(由父到子进行传递)
- 但是对于有一些场景:比如一些数据需要在多个组件中进行共享(地区偏好、ui主题、用户登录状态、用户信息等)
- 如果我们在顶层的App中定义这些信息,之后一层层传递下去,那么对于一些中间层不需要数据的组件来说,是一种冗余的操作
react提供了一个api:Context
- context提供了一种在组件之间共享此类值的方式,而不必显式地通过组件树得逐层传递props
- context设计目的是为了共享那些对于一个组件树而言是“全局”得数据,例如当前认证的用户、主题或首选语言
(后面会讲redux,提供一个单独的库,就不需要这个了)
1.创建context
jsx
import React from 'react';
// 创建 Context,可以设置默认值
const ThemeContext = React.createContext({
color: 'blue',
fontSize: '16px'
});2.使用Provider提供数据
jsx
function App() {
// 准备要共享的数据
const theme = {
color: 'red',
fontSize: '20px',
mode: 'dark'
};
return (
// 用 Provider 包裹需要共享数据的组件
<ThemeContext.Provider value={theme}>
<Header />
<Content />
<Footer />
</ThemeContext.Provider>
);
}3.在子组件中消费数据
jsx
import React, { useContext } from 'react';
function Header() {
// 使用 useContext 获取 Context 值
const theme = useContext(ThemeContext);
return (
<header style={{ color: theme.color, fontSize: theme.fontSize }}>
<h1>网站标题</h1>
<Navigation />
</header>
);
}
function Navigation() {
// 任何深度的子组件都可以直接获取 Context
const theme = useContext(ThemeContext);
return (
<nav style={{ backgroundColor: theme.mode === 'dark' ? '#333' : '#fff' }}>
<a href="#">首页</a>
<a href="#">关于</a>
</nav>
);
}- 什么时候使用Context.Consumer呢?
- 1.当使用value的组件是一个函数式组件时
- 2.当组件中需要多个Context时
provider和consumer这两个双标签中间内容的作用
<ThemeContext.Provider> 中间的内容
作用:定义哪些组件可以访问 Context
jsx
<ThemeContext.Provider value={theme}>
{/* 这里的所有组件和子组件都能访问到 theme 值 */}
<Header />
<Content />
<Footer />
</ThemeContext.Provider>相当于:划定一个"特权区域",在这个区域内的所有组件都能使用这个 Context。
实际例子:
jsx
function App() {
const [theme, setTheme] = useState('light');
return (
<ThemeContext.Provider value={theme}>
{/* 这些组件都能拿到 theme 值 */}
<Header /> {/* 可以访问 theme */}
<Content /> {/* 可以访问 theme */}
<Sidebar /> {/* 可以访问 theme */}
</ThemeContext.Provider>
);
}<ThemeContext.Consumer> 中间的内容
作用:具体如何使用 Context 值
jsx
<ThemeContext.Consumer>
{theme => (
/* 这里定义如何渲染,基于 theme 值 */
<div style={{ background: theme === 'light' ? 'white' : 'black' }}>
当前主题: {theme}
</div>
)}
</ThemeContext.Consumer>相当于:一个"使用门票的环节",在这里具体消费和使用 Context 的值。
