react 状态管理
状态提升 - 组件间共享状态
当想要整合两个组件时,将它们的 state 移动到父组件中, 然后在父组件通过 props 将信息传递下去, 最后,向下传递事件处理程序,以便子组件可以改变父组件的 state
这种模式下叫做受控组件:
- 受控组件 (由
props) 驱动 - 非受控组件 (由
state) 驱动
UI 树同位置 - 状态保留
处在相同 UI 树位置的组件,将保留其中的 state
修改组件输入时重置 state: 给组件定义一个唯一的 key
通过 context 向深层节点透传 props
定义 Context
jsx
import { createContext } from "react";
export const SomeContext = createContext(1);获取 Context
jsx
const level = useContext(SomeContext);传递 Context
jsx
import { SomeContext } from "./app-context.js";
export default function Father({ level, children }) {
return (
<SomeContext.Provider value={level}>
<Child />
</SomeContext.Provider>
);
}与 vue 中的 provider/inject 的区别:
- 语法和使用方式:
Context:React 使用createContext()创建Context对象,通过Provider提供值,Consumer或useContext消费值provide/inject:Vue 直接在组件中使用 provide 提供数据,在子组件中使用inject注入数据
- 响应性:
Context:Context的值变化会触发使用该Context的组件重新渲染provide/inject:默认情况下不是响应式的。但如果提供的是可监听对象,其属性仍然是响应式的
- 使用范围:
Context:适用于多层级组件间共享数据,但过度使用可能影响组件复用性provide/inject:主要用于祖先组件向后代组件传递数据,使用相对简单
- 默认值设置:
Context:在createContext()时可以设置默认值provide/inject:在vue 2.5.0+版本中,inject可以通过设置默认值使其成为可选项
- 组件耦合:
Context:使用Context可能会使组件与特定Context耦合,影响复用性provide/inject:相对来说,provide/inject的使用不会严重影响组件的独立性和复用性
使用 Context 前,先考虑 直接使用 props 或 抽象组件将 jsx 作为 children 传递是否更适用
与 Context 优化相关的:React.memo; Rect.useMemo()
更新 context 时,所有使用该上下文的组件都被重新渲染,为了防止不必要的重新渲染,我们可以:
#1创建多个context想相关的数据分开存储#2拆分组件并传递所需的值,将子组件包装在React.memo中,通过prop分发context的属性#3使用React.useMemo(), 并将context属性作为依赖项,只有当属性修改时才出发回调函数重新渲染
#2
jsx
const Card = () => {
const appContextValue = useContext(AppContext);
const theme = appContextValue.theme;
return (
<div>
<CardTitle theme={theme} />
<CardDescription theme={theme} />
</div>
);
};
const CardTitle = React.memo(({ theme }) => {
return <h2 style={{ color: theme.text }}>2024 年巴黎奥运会 </h2>;
});
const CardDescription = React.memo(({ theme }) => {
return (
<p style={{ color: theme.text }}>
2024 年巴黎奥运会是第 33 届夏季奥林匹克运动会
</p>
);
});#3
jsx
const Card = () => {
const appContextValue = useContext(AppContext);
const theme = appContextValue.theme;
return useMemo(
() => (
<div>
<CardTitle theme={theme} />
<CardDescription theme={theme} />
</div>
),
[theme]
);
};
const CardTitle = ({ theme }) => {
return <h2 style={{ color: theme.text }}>2024 年巴黎奥运会 </h2>;
};
const CardDescription = ({ theme }) => {
return (
<p style={{ color: theme.text }}>
2024 年巴黎奥运会是第 33 届夏季奥林匹克运动会
</p>
);
};全局状态管理
zustand (目前最流行的 react 状态管理库):