React学习笔记(四)

128 阅读3分钟

Redux

什么是Redux

Redux 是一个 JavaScript 状态管理库,主打 “可预测、集中式、单向数据流”。

通俗解释:把整个应用的全局状态放到一个 “大仓库”(Store) 里,用纯函数(Reducer)根据“动作”(Action)去改,组件只负责订阅 & 触发,数据流动完全单向。

Redux诞生背景

  • React 本身只解决 “视图层”,当组件层级深、兄弟节点共享、跨页面共享时,“状态提升 + 层层回调” 会让代码变成 “props 地狱”。
  • Redux 提供 独立于组件树之外 的 全局数据层。

Redux三大核心概念

概念类比说明
Store大仓库全局状态树,单一数据源
Action请假条plain object,必须有 type 字段,描述“发生了什么”
Reducer纯函数出纳接收旧 state + action,返回新 state,无副作用

Redux工作流程(单向数据流)

┌─────────────┐
│  组件触发事件 │
└─────┬───────┘
      │ dispatch({ type: 'ADD_TODO', payload: 'Learn Redux' })
      ▼
┌──────────────┐
│   Action     │  (plain object)
└─────┬────────┘
      ▼
┌──────────────┐
│   Reducer    │  (prevState, action) => newState
└─────┬────────┘
      ▼
┌──────────────┐
│    Store     │  保存新 state
└─────┬────────┘
      ▼
┌──────────────┐
│  订阅的组件   │  自动重新取数 & 渲染
└──────────────┘

Redux示例

import { createStore } from 'redux';

// 1. Reducer:根据动作返回新状态
function counterReducer(state = 0, action) {
  switch (action.type) {
    case 'INCREMENT': return state + 1;
    case 'DECREMENT': return state - 1;
    default: return state;
  }
}

// 2. 创建仓库
const store = createStore(counterReducer);

// 3. 订阅
store.subscribe(() => console.log('当前值:', store.getState()));

// 4. 触发动作
store.dispatch({ type: 'INCREMENT' }); // 1
store.dispatch({ type: 'INCREMENT' }); // 2

Redux使用场景

Redux不用Redux
多组件、跨页面共享数据局部状态,父子几层以内
状态更新逻辑复杂、可回溯简单表单、开关
需要时间旅行调试、快照数据来自服务器即可,无需本地副本
团队大,需要统一规范小项目、快速原型

React-Redux

React-Redux 就是把 Redux 的“中央仓库” 接到 React 组件树 上的官方绑定库。

没有使用React-Redux的情况

需要自己执行如下订阅相关的代码:

store.subscribe(() => {
  const state = store.getState();
  root.render(<App state={state} dispatch={store.dispatch} />);
});
  • 性能差:任何一粒数据变动都整树重新渲染
  • 手动传递dispatch层层钻
  • 难以精确订阅局部状态

React-Redux核心能力

API作用
<Provider store>把 Store 放进 React 上下文,所有组件都能拿到
useSelectorHook:选一块状态,变化才重新渲染组件
useDispatchHook:拿到 dispatch 函数,随时发 Action
connect()HOC(旧API):类组件时代的高阶组件注入

React-Redux用法

函数组件

// 1. 入口挂 Provider
import { Provider } from 'react-redux';
import { store } from './store';

root.render(
  <Provider store={store}>
    <App />
  </Provider>
);

// 2. 组件里直接读/写
import { useSelector, useDispatch } from 'react-redux';

function Counter() {
  const count = useSelector(state => state.counter); // 订阅片段
  const dispatch = useDispatch();                    // 拿派发器

  return (
    <div>
      <p>{count}</p>
      <button onClick={() => dispatch(increment())}>+1</button>
    </div>
  );
}
  • 精准订阅:count没变就不重渲染
  • 无需props层层传递:任何深度组件都能直接useSelector

类组件(connect)

import { connect } from 'react-redux';

class Counter extends React.Component {
  render() {
    const { count, increment } = this.props;
    return (
      <div>
        <p>{count}</p>
        <button onClick={increment}>+1</button>
      </div>
    );
  }
}

// 把 state 和 actionCreator 映射成 props
export default connect(
  state => ({ count: state.counter }),
  { increment }
)(Counter);

性能优化内置

  • useSelector默认使用 严格相等 比较,可传入浅比较函数
  • 订阅粒度到字段级,避免父组件渲染带动子组件
  • 批量更新:一次事件循环内多次dispatch只会触发一次重渲染(React 18 自动 batch)

React-Redux与Redux Toolkit的关系

  • Redux Toolkit 负责 “怎么写仓库”(简化语法)
  • React-Redux 负责 “怎么连仓库”(让组件用得上)

二者搭配 = 官方推荐现代方案