1. React状态管理入门:什么是状态管理、为什么需要状态管理、React中的状态与props的区别
好,咱们开始第一课。
说实话,我见过不少新手一上来就扎进 Redux、Zustand 这些库,结果学了半天还是懵的。为什么?因为连最基础的问题都没搞明白——状态管理到底是什么?
这一章,咱们就把地基打牢。不扯虚的,直接上干货。
1.1 什么是状态管理
先问个问题:你写 React 组件的时候,那些会变的数据,比如用户输入、接口返回、开关状态……它们都放哪了?
嗯,答案就是——状态(State)。
状态管理,说白了就是一套组织、更新、共享这些数据的方法论。
核心定义:状态管理 = 数据 + 数据的变化逻辑 + 数据在组件间的流动方式。
举个例子。你写一个计数器:
function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
这里的 count 是状态,setCount 是更新逻辑,组件重新渲染是数据流动的结果。这其实就是最基础的状态管理。
我个人习惯把状态管理分成三个层次:
- 组件内部状态:用
useState搞定,自己管自己。 - 跨组件状态:需要提升到父组件,或者用 Context。
- 全局状态:多个不相关的组件都要用,这时候才需要 Redux 这类工具。
我在项目中遇到过不少团队,一上来就用 Redux 管理所有状态,连个输入框的值都要走全局 store。结果代码又臭又长,维护起来想哭。记住:能用局部状态解决的问题,别往全局塞。
1.2 为什么需要状态管理
你可能会想:我用 useState 不也能写项目吗?为什么还要学状态管理?
好问题。咱们来看一个真实场景。
假设你做一个购物车页面:
- 商品列表组件要显示数量
- 购物车图标要显示总件数
- 结算组件要计算总价
- 用户登录后还要同步购物车数据
如果只用 useState,你会怎么做?
嗯,大概率是:把状态放在最顶层的 App 组件,然后一层层用 props 往下传。组件多了,你就得经历「props 层层传递」的痛苦——明明中间组件不需要这个数据,却要帮忙传一手。这就是所谓的「prop drilling」。
我曾经接手过一个项目,一个状态从顶层传到第 7 层子组件,中间 5 个组件纯粹是「传话筒」。改一个字段,要改 6 个文件。那感觉,就像在玩「传话游戏」,最后传出来的东西对不对全靠运气。
所以,为什么需要状态管理?说白了就三点:
- 避免 prop drilling:让数据直达需要的组件,中间组件不用当「二传手」。
- 统一数据源:同一个数据只有一个来源,不会出现「A 组件改了数据,B 组件不知道」的情况。
- 可预测的数据流:数据怎么来、怎么变、变到哪里去,一目了然。调试起来也方便。
你想想看,一个项目如果数据流是混乱的,Bug 就会像野草一样,割了一茬又长一茬。状态管理就是给你一把「除草机」。
1.3 React中的状态与props的区别
这个点,我每次面试新人都会问。能讲清楚的人,React 基础基本没问题。
咱们直接上对比表:
| 对比维度 | State(状态) | Props(属性) |
|---|---|---|
| 数据来源 | 组件内部自己管理 | 父组件传递过来 |
| 可变性 | 可变(通过 setState) | 不可变(只读) |
| 谁可以修改 | 组件自身 | 父组件(通过回调) |
| 用途 | 存储动态数据 | 配置组件、传递数据 |
| 触发渲染 | setState 会触发重新渲染 | 父组件重新渲染时,子组件跟着渲染 |
光看表可能有点抽象。咱们写个例子:
// 父组件
function Parent() {
const [name, setName] = useState('张三'); // 这是 state
return (
<div>
<Child name={name} /> {/* 把 state 作为 props 传给子组件 */}
<button onClick={() => setName('李四')}>改名</button>
</div>
);
}
// 子组件
function Child(props) {
// props.name 是只读的,不能直接修改
return <p>我的名字是:{props.name}</p>;
}
这里有几个关键点:
name是Parent组件的 state,它自己管自己。Child组件通过props.name拿到数据,但不能直接改。- 如果
Child想改名字,只能通过父组件传一个回调函数下去。
小技巧:我判断一个数据该用 state 还是 props,就一句话——「这个数据会变吗?如果会变,是谁让它变的?」。如果是组件自己让它变,用 state;如果是别人传进来的,用 props。
嗯,这里要注意一个常见的坑:不要直接修改 props。我见过有人这么写:
// ❌ 错误写法
function Child(props) {
props.name = '王五'; // 直接修改 props!React 会警告
return <p>{props.name}</p>;
}
为什么不行?因为 props 是只读的。你改了父组件也不知道,数据就乱套了。正确的做法是:
// ✅ 正确写法
function Child(props) {
const [localName, setLocalName] = useState(props.name); // 如果需要修改,复制一份到本地 state
return <p>{localName}</p>;
}
说白了,state 和 props 的关系就像「家产」和「礼物」:state 是你自己挣的钱,想怎么花都行;props 是别人送你的东西,你可以用,但不能随便改。想改?得先跟送礼的人商量(调用父组件的回调)。
这一章的内容就到这里。记住:状态管理不是银弹,但理解它的本质,能让你在 React 的世界里走得更远。下一章,咱们聊聊 React 自带的 useState 和 useReducer,看看它们到底怎么用才顺手。