Web 前端手册WEB FRONTEND

CHAPTER 06应用层 · STATE

状态管理

Redux/Pinia/Vuex、Context、服务端状态与缓存策略。分清"客户端状态"和"服务端状态",别混为一谈。

开始阅读难度进阶先修第四章约2小时
06.1

客户端与服务端状态

客户端状态(表单输入、开关、主题)是同步、本地的;服务端状态(接口数据)是异步、远程的,会过期、需缓存与失效。两者用不同工具管理。

别用全局 store 存所有把服务端数据塞进 Redux/Pinia 会重复造缓存轮子。交给 React Query/SWR/TanStack Query 这类库更省心。

06.2

组件内状态

局部 UI 状态优先留在组件内(useState/ref)。只在该状态需要被多组件共享时再提升或外置。

const [open, setOpen] = useState(false);  // 仅本组件用的状态
06.3

Context 共享

React Context 适合低频共享(主题、登录用户)。高频变化的状态用 Context 会导致大范围重渲染,应慎用或拆分。

const ThemeCtx = createContext('light');
function App() {
  return <ThemeCtx.Provider value="dark"><Child/></ThemeCtx.Provider>;
}
Context 重渲染

Provider value 变化会使所有消费组件重渲染。用 useMemo 稳定 value,或拆成多个 Context 隔离变化。

06.4

Redux 模式

Redux 是集中式、可预测的客户端状态容器:state + action + reducer,配合 Redux Toolkit 大幅简化样板。

const counter = createSlice({
  name: 'counter',
  initialState: { value: 0 },
  reducers: { inc: s => { s.value++; } }
});
06.5

Pinia

Vue 的 Pinia 是响应式、类型友好的集中状态库,比 Vuex 更简洁:定义 store,组件里直接读写并自动更新。

export const useCart = defineStore('cart', {
  state: () => ({ items: [] as string[] }),
  actions: { add(i: string) { this.items.push(i); } }
});
06.6

服务端状态

React Query/SWR 把"取数、缓存、失效、重试"封装好:自动去重请求、按 key 缓存、后台刷新,组件只声明"我要这个数据"。

const { data, isLoading } = useQuery({
  queryKey: ['user', id],
  queryFn: () => fetchUser(id)
});
06.7

选型建议

小项目组件内状态 + Context 足够;跨页面共享的客户端状态用 Pinia/Redux;服务端数据交给 Query 类库。别过度引入。

场景推荐
局部 UI组件内 state
低频全局(主题/用户)Context / store
高频共享客户端状态Pinia / Redux
接口数据React Query / SWR
06.8

常见陷阱与 FAQ

所有状态都放全局 store?

不需要。局部状态全局化会增加耦合与重渲染范围。遵循"最小共享"原则,能局部就不提升。

直接修改 store 状态?
Vue/Pinia 可直接改;Redux 必须用 action 触发 reducer 返回新状态,否则不可追踪、不触发更新。

服务端数据自己写缓存?

尽量避免。用成熟 Query 库处理缓存、失效与竞态,比手写更稳、更少 bug。

06.9

实战练习与资源

延伸资源