1. 基本概念
1.1 Redux
Redux 是一个独立的状态管理库,可以与任何 UI 库或框架一起使用,不仅限于 React。它提供了以下核心功能:
- Store:存储状态的容器
- Action:描述状态变化的对象
- Reducer:处理状态更新的纯函数
- Dispatch:触发状态更新的方法
1.2 React-Redux
React-Redux 是 Redux 的 React 官方绑定库,它提供了在 React 应用中使用 Redux 的专用工具和组件:
- Provider:提供 Redux store 的上下文
- connect:连接 React 组件与 Redux store(类组件)
- Hooks:提供在函数组件中使用 Redux 的钩子(useSelector, useDispatch)
2. 主要区别
2.1 使用范围
// Redux - 可以在任何 JavaScript 环境中使用
import { createStore } from 'redux';
const store = createStore(reducer);
store.subscribe(() => console.log(store.getState()));
store.dispatch({ type: 'INCREMENT' });
// React-Redux - 专门用于 React 环境
import { Provider, useSelector, useDispatch } from 'react-redux';
function App() {
return (
<Provider store={store}>
<Counter />
</Provider>
);
}
2.2 状态访问方式
// Redux - 直接访问 store
const state = store.getState();
store.dispatch({ type: 'INCREMENT' });
// React-Redux - 通过 hooks 或 connect 访问
function Counter() {
const count = useSelector(state => state.count);
const dispatch = useDispatch();
return (
<button onClick={() => dispatch({ type: 'INCREMENT' })}>
Count: {count}
</button>
);
}
2.3 更新订阅方式
// Redux - 手动订阅更新
store.subscribe(() => {
console.log('State updated:', store.getState());
});
// React-Redux - 自动处理订阅和更新
function Counter() {
// 自动订阅更新,组件会在相关状态变化时重新渲染
const count = useSelector(state => state.count);
return <div>{count}</div>;
}
3. 联系
3.1 工作流程
// 1. 创建 Redux store
const store = createStore(reducer);
// 2. 使用 React-Redux 连接 React 应用
function App() {
return (
<Provider store={store}>
<Counter />
</Provider>
);
}
// 3. 在组件中使用 Redux 状态
function Counter() {
const count = useSelector(state => state.count);
const dispatch = useDispatch();
return (
<button onClick={() => dispatch({ type: 'INCREMENT' })}>
{count}
</button>
);
}
3.2 数据流向
// Redux 和 React-Redux 共同维护单向数据流
// 1. Action 创建
const increment = () => ({ type: 'INCREMENT' });
// 2. Redux reducer 处理
const reducer = (state = 0, action) => {
switch (action.type) {
case 'INCREMENT':
return state + 1;
default:
return state;
}
};
// 3. React-Redux 连接组件
function Counter() {
const count = useSelector(state => state);
const dispatch = useDispatch();
return (
<div>
<p>Count: {count}</p>
<button onClick={() => dispatch(increment())}>
Increment
</button>
</div>
);
}
4. 使用场景对比
4.1 何时使用 Redux
- 需要在非 React 环境中使用状态管理
- 需要更底层的状态管理控制
- 需要与其他框架集成
// Redux 独立使用示例
const store = createStore(reducer);
// 可以在任何地方使用
document.getElementById('button')
.addEventListener('click', () => {
store.dispatch({ type: 'INCREMENT' });
});
store.subscribe(() => {
document.getElementById('count')
.textContent = store.getState();
});
4.2 何时使用 React-Redux
- 在 React 应用中使用 Redux
- 需要更好的性能优化
- 需要更简洁的 API
// React-Redux 使用示例
function Counter() {
const count = useSelector(state => state.count);
const dispatch = useDispatch();
// 自动处理性能优化
return (
<button onClick={() => dispatch({ type: 'INCREMENT' })}>
Count: {count}
</button>
);
}
5. 性能考虑
5.1 Redux 性能优化
// 手动优化订阅
let previousState = store.getState();
store.subscribe(() => {
const currentState = store.getState();
if (previousState.count !== currentState.count) {
// 只在相关状态变化时更新
updateUI();
}
previousState = currentState;
});
5.2 React-Redux 性能优化
// 使用 reselect 优化选择器
import { createSelector } from '@reduxjs/toolkit';
const selectCount = state => state.count;
const selectDoubleCount = createSelector(
selectCount,
count => count * 2
);
function Counter() {
// 只在 count 变化时重新计算
const doubleCount = useSelector(selectDoubleCount);
return <div>{doubleCount}</div>;
}
6. 最佳实践
6.1 Redux 最佳实践
- 保持 store 结构扁平
- 使用不可变更新模式
- 规范化状态结构
6.2 React-Redux 最佳实践
- 使用 hooks API 而不是 connect
- 合理使用 selector
- 避免过度订阅
7. 总结
7.1 主要区别
- 使用范围:Redux 更通用,React-Redux 专注于 React
- API 设计:React-Redux 提供更简洁的 API
- 性能优化:React-Redux 提供自动优化
7.2 关键联系
- React-Redux 依赖 Redux 核心功能
- 共同维护单向数据流
- 遵循相同的状态管理原则
7.3 选择建议
- React 项目推荐使用 React-Redux
- 需要跨框架使用时选择 Redux
- 大型应用可以同时使用两者的特性