React从入门到出门第四章 组件通讯与全局状态管理
大家好~ 前面我们已经掌握了 React 19 的函数组件、Hooks、虚拟 DOM 等核心基础,今天咱们聚焦 React 应用开发中的核心问题——组件间的通信。
在 React 应用中,组件不是孤立的,它们需要通过“传递数据”协同工作:小到父子组件间的简单数据传递,大到跨层级、多组件共享的全局状态管理,都是日常开发中高频遇到的场景。
很多新手会在“该用哪种传参方式”“什么时候需要全局状态”这些问题上困惑。今天这篇文章,我们就从“组件关系”出发,按“简单到复杂”的顺序,拆解 React 19 中的组件传参方案,再深入讲解全局状态管理的核心思路与常用方案,结合代码示例和图例,让大家能根据实际场景灵活选择~
一、先明确:组件关系决定传参方案
在 React 应用中,组件间的关系主要分为 3 类:父子组件、兄弟组件、跨层级组件(祖孙/远亲) 。不同关系对应的传参难度和方案不同,我们先通过一个图例理清组件关系模型:
核心原则:能局部传参就不全局——局部传参(如父子、兄弟)简单直观、性能开销小,全局状态(如 Redux、Context)适合共享数据多、跨层级广的场景,避免过度设计。
二、React 19 组件传参方案全解析(按场景分类)
1. 父子组件传参:最基础的“props 向下+回调向上”
父子组件是最常见的关系,传参核心依赖 props:父组件通过 props 向子组件传递数据(向下传),子组件通过 props 接收父组件的回调函数,将数据传递回父组件(向上传),形成“双向通信”。
场景 1:父传子(数据向下传递)
核心逻辑:父组件在使用子组件时,通过“属性=值”的形式传递数据,子组件通过参数 props 接收(可解构简化)。
// 父组件:传递数据给子组件
function Parent() {
const parentData = "我是父组件的数据";
const userInfo = { name: "小明", age: 22 };
return (
<div>
<h3>父组件</h3>
{/* 通过 props 传递基础类型、对象等数据 */}
<Child
msg={parentData}
user={userInfo}
isShow={true}
/>
</div>
);
}
// 子组件:接收并使用父组件传递的数据
// 方式 1:直接通过 props 参数接收
// function Child(props) {
// return <p>父组件传递的消息:{props.msg}</p>;
// }
// 方式 2:解构 props,更简洁(推荐)
function Child({ msg, user, isShow }) {
return (
<div>
<h4>子组件</h4>
{isShow && <p>父组件传递的消息:{msg}</p>}
<p>用户姓名:{user.name},年龄:{user.age}</p>
</div>
);
}
注意:props 是只读的!子组件不能直接修改 props 的值(如不能写 user.age = 23),若需修改,需通过“子传父”的方式让父组件更新数据。
场景 2:子传父(数据向上传递)
核心逻辑:父组件传递一个“回调函数”给子组件,子组件触发该函数时,将需要传递的数据作为参数传入,父组件在回调函数中接收并处理数据。
// 父组件:传递回调函数给子组件
function Parent() {
const [childData, setChildData] = useState("");
// 回调函数:接收子组件传递的数据
const handleChildMsg = (data) => {
console.log("子组件传递的数据:", data);
setChildData(data); // 更新父组件状态
};
return (
<div>
<h3>父组件</h3>
<p>子组件传递的消息:{childData}</p>
{/* 传递回调函数 */}
<Child onSendMsg={handleChildMsg} />
</div>
);
}
// 子组件:触发回调函数,传递数据给父组件
function Child({ onSendMsg }) {
const [inputValue, setInputValue] = useState("");
const handleSubmit = () => {
// 触发父组件传递的回调函数,传入数据
onSendMsg(inputValue);
setInputValue(""); // 清空输入框
};
return (
<div>
<h4>子组件</h4>
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
placeholder="输入要传递给父组件的内容"
/>
<button onClick={handleSubmit} style={{ marginLeft: "10px" }}>
发送给父组件
</button>
</div>
);
}
场景 3:父子双向绑定(表单常见)
核心逻辑:结合“父传子”和“子传父”,父组件传递数据给子组件(表单默认值),子组件通过回调函数将修改后的值传递回父组件,实现“数据同步”。
// 父组件:管理表单状态
function Parent() {
const [username, setUsername] = useState("");
// 接收子组件修改后的值,更新父组件状态
const handleUsernameChange = (newValue) => {
setUsername(newValue);
};
return (
<div>
<h3>父组件:{username}</h3>
{/* 传递状态(默认值)和回调函数 */}
<Input
value={username}
onChange={handleUsernameChange}
placeholder="请输入用户名"
/>
</div>
);
}
// 子组件:表单输入组件
function Input({ value, onChange, placeholder }) {
// 输入变化时,触发回调函数传递新值
const handleInput = (e) => {
onChange(e.target.value);
};
return (
<input
type="text"
value={value}
onChange={handleInput}
placeholder={placeholder}
style={{ width: "300px", height: "30px", padding: "0 8px" }}
/>
);
}
2. 兄弟组件传参:通过父组件中转
兄弟组件间没有直接的通信通道,需通过“共同的父组件”作为中转:先让“发送数据的兄弟”将数据传递给父组件,再由父组件将数据传递给“接收数据的兄弟”。
用图例展示通信流程:
实战案例:兄弟组件数据同步
// 父组件:作为兄弟组件的中转
function Parent() {
const [sharedData, setSharedData] = useState("");
// 接收 Child1 传递的数据
const handleDataFromChild1 = (data) => {
setSharedData(data);
};
return (
<div>
<h3>父组件(中转)</h3>
{/* 兄弟 1:发送数据 */}
<Child1 onSendData={handleDataFromChild1} />
{/* 兄弟 2:接收数据 */}
<Child2 receivedData={sharedData} />
</div>
);
}
// 兄弟 1:发送数据的组件
function Child1({ onSendData }) {
const [inputValue, setInputValue] = useState("");
const handleSend = () => {
onSendData(inputValue);
setInputValue("");
};
return (
<div>
<h4>兄弟组件 1(发送方)</h4>
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
placeholder="输入要传递给兄弟的数据"
/>
<button onClick={handleSend} style={{ marginLeft: "10px" }}>
发送给兄弟
</button>
</div>
);
}
// 兄弟 2:接收数据的组件
function Child2({ receivedData }) {
return (
<div>
<h4>兄弟组件 2(接收方)</h4>
<p>收到兄弟 1 的数据:{receivedData || "暂无数据"}</p>
</div>
);
}
3. 跨层级组件传参:Context API(React 19 原生方案)
当组件层级很深(如“爷爷→爸爸→儿子→孙子”),或者跨多个层级传递数据时,用 props 层层传递(即“props drilling”)会非常繁琐,且代码可维护性差。这时可以用 React 原生的 Context API 解决。
Context API 的核心作用:创建一个“全局数据容器”,让所有后代组件都能直接访问容器中的数据,无需层层传递 props。
使用步骤:3 步搞定 Context 传参
- 创建 Context:用
createContext创建一个 Context 对象(可设置默认值); - 提供 Context:用
Context.Provider包裹需要共享数据的组件树,通过value属性传入共享数据; - 消费 Context:后代组件用
useContextHook 直接获取共享数据。
实战案例:跨层级共享主题状态
import { createContext, useContext, useState } from 'react';
// 步骤 1:创建 Context(默认值仅在无 Provider 时生效)
const ThemeContext = createContext("light");
// 步骤 2:提供 Context 的组件(通常是顶层组件)
function App() {
const [theme, setTheme] = useState("light");
// 共享的方法:切换主题
const toggleTheme = () => {
setTheme(prev => prev === "light" ? "dark" : "light");
};
// 要共享的数据和方法(封装成对象)
const contextValue = {
theme,
toggleTheme
};
return (
// 步骤 2:用 Provider 包裹组件树,传入共享数据
<ThemeContext.Provider value={contextValue}>
<div style={{ padding: "20px" }}>
<h2>顶层组件(提供 Context)</h2>
<Parent /> {/* 父组件 */}
</div>
</ThemeContext.Provider>
);
}
// 父组件(中间层级,无需传递 theme 相关 props)
function Parent() {
return (
<div style={{ border: "1px solid #ccc", padding: "20px", marginTop: "10px" }}>
<h3>父组件(中间层级)</h3>
<Child /> {/* 子组件 */}
</div>
);
}
// 子组件(后代组件,直接消费 Context)
function Child() {
// 步骤 3:用 useContext 获取共享数据
const { theme, toggleTheme } = useContext(ThemeContext);
// 根据主题设置样式
const containerStyle = {
border: "1px solid #ccc",
padding: "20px",
marginTop: "10px",
background: theme === "light" ? "#fff" : "#333",
color: theme === "light" ? "#333" : "#fff"
};
return (
<div style={containerStyle}>
<h4>子组件(消费 Context)</h4>
<p>当前主题:{theme}</p>
<button onClick={toggleTheme}>切换主题</button>
</div>
);
}
Context API 适合场景:共享“变化不频繁”的全局数据(如主题、用户登录状态、语言设置)。如果需要频繁更新数据,且涉及复杂逻辑(如多组件修改同一状态),建议结合 useReducer 或专门的全局状态管理库。
三、全局状态管理:从 Context+useReducer 到专业库
当应用规模扩大,需要共享的数据增多、状态更新逻辑复杂(如购物车、用户中心、多页面共享筛选条件)时,单纯的 Context API 就不够用了(比如多个组件修改 Context 数据时,逻辑分散,难以维护)。这时就需要“全局状态管理”方案。
React 19 中常用的全局状态管理方案有 3 类:Context+useReducer(原生方案)、Redux Toolkit(生态主流)、Zustand/Jotai(轻量方案) 。我们分别讲解它们的核心思路和适用场景。
1. 原生方案:Context+useReducer(适合中小型应用)
useReducer 是 React 内置的 Hooks,用于处理“复杂状态逻辑”——当状态更新依赖于前一个状态、或者有多个子值需要同步更新时,useReducer 比 useState 更清晰。
Context+useReducer 的核心思路:用 useReducer 管理全局状态的更新逻辑,用 Context 提供和共享状态与 dispatch 方法,实现“状态集中管理+全局共享”。
实战案例:全局购物车状态管理
import { createContext, useContext, useReducer } from 'react';
// 步骤 1:创建 Context
const CartContext = createContext();
// 步骤 2:定义 reducer 函数(集中处理状态更新逻辑)
// reducer 接收两个参数:当前状态 state、动作 action(包含 type 和 payload)
function cartReducer(state, action) {
switch (action.type) {
// 新增商品
case "ADD_ITEM":
// 先判断商品是否已存在
const existingItem = state.find(item => item.id === action.payload.id);
if (existingItem) {
// 已存在:更新数量
return state.map(item =>
item.id === action.payload.id
? { ...item, count: item.count + 1 }
: item
);
} else {
// 不存在:新增商品
return [...state, { ...action.payload, count: 1 }];
}
// 删除商品
case "REMOVE_ITEM":
return state.filter(item => item.id !== action.payload.id);
// 清空购物车
case "CLEAR_CART":
return [];
default:
return state;
}
}
// 步骤 3:创建 Provider 组件,提供状态和 dispatch
function CartProvider({ children }) {
// 用 useReducer 管理状态:初始状态为空数组
const [cartState, dispatch] = useReducer(cartReducer, []);
// 共享的数据和方法
const contextValue = {
cartState, // 购物车状态
// 封装 dispatch 方法(让组件更易用,无需直接写 action)
addItem: (item) => dispatch({ type: "ADD_ITEM", payload: item }),
removeItem: (id) => dispatch({ type: "REMOVE_ITEM", payload: { id } }),
clearCart: () => dispatch({ type: "CLEAR_CART" })
};
return (
<CartContext.Provider value={contextValue}>
{children}
</CartContext.Provider>
);
}
// 步骤 4:消费全局状态的组件
// 组件 1:商品列表(添加商品到购物车)
function ProductList() {
const { addItem } = useContext(CartContext);
// 模拟商品数据
const products = [
{ id: 1, name: "React 实战教程", price: 99 },
{ id: 2, name: "Vue 实战教程", price: 89 },
{ id: 3, name: "TypeScript 教程", price: 79 }
];
return (
<div>
<h3>商品列表</h3>
<div style={{ display: "flex", gap: "20px", margin: "10px 0" }}>
{products.map(product => (
<div key={product.id} style={{ border: "1px solid #ccc", padding: "10px" }}>
<p>{product.name}</p>
<p>价格:{product.price} 元</p>
<button onClick={() => addItem(product)}>加入购物车</button>
</div>
))}
</div>
</div>
);
}
// 组件 2:购物车(展示/删除/清空商品)
function Cart() {
const { cartState, removeItem, clearCart } = useContext(CartContext);
// 计算总价格
const totalPrice = cartState.reduce((total, item) => {
return total + item.price * item.count;
}, 0);
return (
<div style={{ marginTop: "20px", border: "1px solid #ccc", padding: "20px" }}>
<h3>购物车({cartState.length} 种商品)</h3>
{cartState.length === 0 ? (
<p>购物车为空</p>
) : (
<>
{cartState.map(item => (
<div key={item.id} style={{ display: "flex", gap: "10px", margin: "10px 0" }}>
<p>{item.name} × {item.count}</p>
<p>{item.price * item.count} 元</p>
<button onClick={() => removeItem(item.id)}>删除</button>
</div>
))}
<p>总价:{totalPrice} 元</p>
<button onClick={clearCart} style={{ marginTop: "10px" }}>清空购物车</button>
</>
)}
</div>
);
}
// 根组件
function App() {
return (
<CartProvider>
<div style={{ padding: "20px" }}>
<h2>全局购物车管理(Context+useReducer)</h2>
<ProductList />
<Cart />
</div>
</CartProvider>
);
}
2. 生态主流:Redux Toolkit(适合大型复杂应用)
Redux 是 React 生态中最成熟的全局状态管理库,而 Redux Toolkit(RTK)是官方推荐的 Redux 简化方案(解决了原生 Redux 代码繁琐、配置复杂的问题)。
核心优势:状态集中管理、可预测性强、支持中间件(如异步请求)、调试工具完善,适合大型应用中多团队协作、复杂状态逻辑的场景。
核心概念与使用步骤(简化)
- 安装依赖:
npm install @reduxjs/toolkit react-redux; - 创建切片(Slice):用
createSlice定义状态初始值、reducer 函数(同步/异步); - 创建 Store:用
configureStore整合所有切片; - 提供 Store:用
Provider(来自 react-redux)包裹根组件; - 消费 Store:用
useSelector获取状态,用useDispatch触发状态更新。
实战案例:Redux Toolkit 实现购物车
// 1. 安装依赖后,创建切片(src/features/cart/cartSlice.js)
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
// 模拟异步请求:从接口获取商品数据(异步 action)
export const fetchProducts = createAsyncThunk(
'cart/fetchProducts',
async () => {
const res = await fetch('https://api.example.com/products');
return res.json();
}
);
// 创建切片
const cartSlice = createSlice({
name: 'cart', // 切片名称(唯一)
initialState: {
products: [], // 商品列表
cartItems: [], // 购物车商品
loading: false, // 加载状态
error: null // 错误信息
},
reducers: {
// 同步 action:添加商品到购物车
addToCart: (state, action) => {
const existingItem = state.cartItems.find(item => item.id === action.payload.id);
if (existingItem) {
existingItem.count += 1;
} else {
state.cartItems.push({ ...action.payload, count: 1 });
}
},
// 同步 action:从购物车删除商品
removeFromCart: (state, action) => {
state.cartItems = state.cartItems.filter(item => item.id !== action.payload);
},
// 同步 action:清空购物车
clearCart: (state) => {
state.cartItems = [];
}
},
// 处理异步 action 的状态(pending/fulfilled/rejected)
extraReducers: (builder) => {
builder
.addCase(fetchProducts.pending, (state) => {
state.loading = true;
})
.addCase(fetchProducts.fulfilled, (state, action) => {
state.loading = false;
state.products = action.payload;
})
.addCase(fetchProducts.rejected, (state, action) => {
state.loading = false;
state.error = action.error.message;
});
}
});
// 导出同步 action
export const { addToCart, removeFromCart, clearCart } = cartSlice.actions;
// 导出 reducer
export default cartSlice.reducer;
// 2. 创建 Store(src/app/store.js)
import { configureStore } from '@reduxjs/toolkit';
import cartReducer from '../features/cart/cartSlice';
export const store = configureStore({
reducer: {
cart: cartReducer // 整合 cart 切片
}
});
// 3. 根组件提供 Store(src/App.js)
import { Provider } from 'react-redux';
import { store } from './app/store';
import ProductList from './features/cart/ProductList';
import Cart from './features/cart/Cart';
function App() {
return (
<Provider store={store}> {/* 提供 Store */}
<div style={{ padding: "20px" }}>
<h2>Redux Toolkit 购物车</h2>
<ProductList />
<Cart />
</div>
</Provider>
);
}
// 4. 消费 Store:商品列表组件(src/features/cart/ProductList.js)
import { useDispatch, useSelector } from 'react-redux';
import { fetchProducts, addToCart } from './cartSlice';
import { useEffect } from 'react';
function ProductList() {
const dispatch = useDispatch();
const { products, loading, error } = useSelector(state => state.cart);
// 组件挂载时获取商品数据
useEffect(() => {
dispatch(fetchProducts());
}, [dispatch]);
if (loading) return <p>加载中...</p>;
if (error) return <p>错误:{error}</p>;
return (
<div>
<h3>商品列表</h3>
<div style={{ display: "flex", gap: "20px", margin: "10px 0" }}>
{products.map(product => (
<div key={product.id} style={{ border: "1px solid #ccc", padding: "10px" }}>
<p>{product.name}</p>
<p>价格:{product.price} 元</p>
<button onClick={() => dispatch(addToCart(product))}>加入购物车</button>
</div>
))}
</div>
</div>
);
}
export default ProductList;
// 5. 消费 Store:购物车组件(src/features/cart/Cart.js)
import { useDispatch, useSelector } from 'react-redux';
import { removeFromCart, clearCart } from './cartSlice';
function Cart() {
const dispatch = useDispatch();
const { cartItems } = useSelector(state => state.cart);
const totalPrice = cartItems.reduce((total, item) => {
return total + item.price * item.count;
}, 0);
return (
<div style={{ marginTop: "20px", border: "1px solid #ccc", padding: "20px" }}>
<h3>购物车({cartItems.length} 种商品)</h3>
{cartItems.length === 0 ? (
<p>购物车为空</p>
) : (
<>
{cartItems.map(item => (
<div key={item.id} style={{ display: "flex", gap: "10px", margin: "10px 0" }}>
<p>{item.name} × {item.count}</p>
<p>{item.price * item.count} 元</p>
<button onClick={() => dispatch(removeFromCart(item.id))}>删除</button>
</div>
))}
<p>总价:{totalPrice} 元</p>
<button onClick={() => dispatch(clearCart())} style={{ marginTop: "10px" }}>清空购物车</button>
</>
)}
</div>
);
}
export default Cart;
3. 轻量方案:Zustand(适合中小型应用,简洁高效)
如果觉得 Redux Toolkit 配置还是繁琐,而 Context+useReducer 在复杂场景下不够灵活,可以选择 Zustand——一个轻量级的全局状态管理库,API 简洁,无需过多配置,深受 React 开发者喜爱。
核心优势:代码简洁、学习成本低、无需 Provider 包裹、支持中间件(异步请求、持久化等) ,适合中小型应用或对开发效率有要求的场景。
实战案例:Zustand 实现购物车
// 1. 安装依赖:npm install zustand
import { create } from 'zustand';
import { useEffect } from 'react';
// 2. 创建 Store
const useCartStore = create((set) => ({
// 状态
products: [],
cartItems: [],
loading: false,
error: null,
// 异步 action:获取商品数据
fetchProducts: async () => {
set({ loading: true, error: null });
try {
const res = await fetch('https://api.example.com/products');
const data = await res.json();
set({ products: data, loading: false });
} catch (err) {
set({ error: err.message, loading: false });
}
},
// 同步 action:添加商品到购物车
addToCart: (product) => {
set((state) => {
const existingItem = state.cartItems.find(item => item.id === product.id);
if (existingItem) {
return {
cartItems: state.cartItems.map(item =>
item.id === product.id ? { ...item, count: item.count + 1 } : item
)
};
} else {
return { cartItems: [...state.cartItems, { ...product, count: 1 }] };
}
});
},
// 同步 action:删除商品
removeFromCart: (id) => {
set((state) => ({
cartItems: state.cartItems.filter(item => item.id !== id)
}));
},
// 同步 action:清空购物车
clearCart: () => {
set({ cartItems: [] });
}
}));
// 3. 商品列表组件
function ProductList() {
// 从 Store 获取状态和方法
const { products, loading, error, fetchProducts, addToCart } = useCartStore();
useEffect(() => {
fetchProducts();
}, [fetchProducts]);
if (loading) return <p>加载中...</p>;
if (error) return <p>错误:{error}</p>;
return (
<div>
<h3>商品列表(Zustand)</h3>
<div style={{ display: "flex", gap: "20px", margin: "10px 0" }}>
{products.map(product => (
<div key={product.id} style={{ border: "1px solid #ccc", padding: "10px" }}>
<p>{product.name}</p>
<p>价格:{product.price} 元</p>
<button onClick={() => addToCart(product)}>加入购物车</button>
</div>
))}
</div>
</div>
);
}
// 4. 购物车组件
function Cart() {
// 从 Store 获取状态和方法
const { cartItems, removeFromCart, clearCart } = useCartStore();
const totalPrice = cartItems.reduce((total, item) => {
return total + item.price * item.count;
}, 0);
return (
<div style={{ marginTop: "20px", border: "1px solid #ccc", padding: "20px" }}>
<h3>购物车({cartItems.length} 种商品)</h3>
{cartItems.length === 0 ? (
<p>购物车为空</p>
) : (
<>
{cartItems.map(item => (
<div key={item.id} style={{ display: "flex", gap: "10px", margin: "10px 0" }}>
<p>{item.name} × {item.count}</p>
<p>{item.price * item.count} 元</p>
<button onClick={() => removeFromCart(item.id)}>删除</button>
</div>
))}
<p>总价:{totalPrice} 元</p>
<button onClick={clearCart} style={{ marginTop: "10px" }}>清空购物车</button>
</>
)}
</div>
);
}
// 5. 根组件
function App() {
return (
<div style={{ padding: "20px" }}>
<h2>Zustand 购物车</h2>
<ProductList />
<Cart />
</div>
);
}
四、全局状态管理方案对比与选择建议
为了让大家能根据项目规模和需求选择合适的方案,我们用表格对比常用的 3 种全局状态管理方案:
| 方案 | 核心优势 | 劣势 | 适用场景 |
|---|---|---|---|
| Context+useReducer | 1. 原生方案,无需额外安装依赖;2. 实现简单,学习成本低;3. 轻量无冗余 | 1. 不支持中间件,处理异步逻辑繁琐;2. 状态更新会触发所有消费组件重渲染(需配合 memo 优化);3. 不适合复杂状态逻辑 | 中小型应用、简单全局状态(如主题、登录状态) |
| Redux Toolkit | 1. 状态集中管理,可预测性强;2. 支持中间件(异步、日志等);3. 调试工具完善;4. 适合多团队协作 | 1. 配置相对繁琐,学习成本高;2. 代码量较多;3. 轻量应用可能显得过重 | 大型复杂应用、多团队协作、复杂状态逻辑(如电商、后台管理系统) |
| Zustand | 1. API 简洁,学习成本低;2. 无需 Provider 包裹;3. 支持中间件,处理异步简单;4. 性能优秀(精准更新) | 1. 生态不如 Redux 完善;2. 大型复杂应用的协作规范不如 Redux 成熟 | 中小型应用、对开发效率有要求的场景、需要轻量方案替代 Context+useReducer |
五、核心总结与避坑指南
核心总结
- 组件传参遵循“就近原则” :父子/兄弟组件用 props+回调,跨层级用 Context API,全局共享用专门的状态管理方案;
- 全局状态管理“按需选择” :小型应用用 Context+useReducer,中型用 Zustand,大型复杂应用用 Redux Toolkit;
- props 是只读的:子组件不能直接修改 props,需通过回调让父组件更新,避免破坏单向数据流;
- 避免过度设计:不要一开始就用全局状态,先尝试局部传参,当局部传参无法满足需求时再引入全局状态。
避坑指南
- 坑 1:滥用 Context API:Context 会导致所有消费组件在状态更新时重渲染,若状态更新频繁,需配合 memo、useMemo 优化;
- 坑 2:Redux 过度使用:不是所有状态都需要放入 Redux,局部状态(如组件内部的表单输入)用 useState 即可;
- 坑 3:列表渲染忘记加 key:传参时若涉及列表渲染,务必给列表项加唯一 key,避免 React 误判节点导致性能问题;
- 坑 4:直接修改状态:无论是局部状态还是全局状态,都要遵循“不可变更新”原则(如用扩展运算符、map 等方法创建新状态),避免直接修改原状态。
六、下一步学习方向
今天我们掌握了 React 19 组件传参与全局状态管理的核心方案,下一步可以重点学习:
- 状态管理性能优化:如 memo、useMemo、useCallback 与状态管理的配合使用;
- 其他轻量状态管理库:如 Jotai、Recoil(原子化状态管理,适合细粒度状态共享);
- Redux 高级特性:如中间件(redux-thunk、redux-saga)、状态持久化(redux-persist);
- React 19 新增状态相关特性:如 useOptimistic(乐观更新)、useActionState(表单状态管理)。
如果这篇文章对你有帮助,欢迎点赞、收藏、转发~ 有任何问题也可以在评论区留言交流~ 我们下期再见!