工具链✅
用过 redux 说下核心概念?
答案
参考 redux 官方文档 redux 的核心概念如下图
- Actions
- ActionCreators
- Reducer
- Store
- Dispatch
- Selectors
- Subscriptions
动作对象(Actions) 表示一个事件对象,通过 UI 或副作用触发,注意这里使用的是 Actions,是为了说明可以定义多个 Action
{
type: 'ACTION_TYPE', // 必须,定义事件的名称
payload: { ... } // 可选,事件携带的信息
}
事件创建函数(Actions Creators) 返回动作对象,本质上就是一个工厂方法,用来简化动作对象的生成
// 支持携带任意参数
function addAction(...args) {
return {
type: 'ADD',
payload: { /* 事件携带的信息 */ }
};
}
状态处理器(Reducer) 接受 当前状态和动作对象,返回新的状态。它是一个纯函数,不能修改原状态,而是返回一个新的状态对象。本质类似 Array 的 reduce
方法, (state, action) => newState
function counterReducer(state = 0, action) {
switch (action.type) {
case 'ADD':
return state + 1;
case 'SUBTRACT':
return state - 1;
default:
return state;
}
}
状态仓库(Store) 通过 createStore
创建,包含当前状态和状态处理器。它是应用的唯一数据源,提供了获取状态、派发动作和订阅状态变化的方法。
import { createStore } from 'redux';
const store = createStore(counterReducer);
// 获取当前状态
const currentState = store.getState();
// 订阅状态变化
store.subscribe(() => {
console.log('状态变化:', store.getState());
});
// 派发动作
store.dispatch(addAction());
状态分发(Dispatch) 通过 store.dispatch(action)
方法触发状态更新。它会调用所有注册的状态处理器,并更新状态。
// 直接派发动作对象
store.dispatch({ type: 'ADD' });
// 或者使用事件创建函数
store.dispatch(addAction());
状态提取(Selectors) 用于从状态中提取特定数据。它是一个函数,接受当前状态作为参数,返回所需的数据。
const getCounterValue = (state) => state.counter;
const counterValue = getCounterValue(store.getState());
状态订阅(Subscriptions) 允许组件订阅状态的变化,以便在状态更新时重新渲染。它是一个函数,接受当前状态作为参数,返回所需的数据。
// 返回一个取消订阅的函数
const unsubscribe = store.subscribe(() => {
console.log('状态变化:', store.getState());
});
// 取消订阅
unsubscribe();
示例代码
Redux 的状态是只读的,不能直接修改。所有的状态变更都需要通过派发动作来实现。同时 reducer 必须是纯函数,不能有副作用。
说一下 redux
、@reduxjs/toolkit
、react-redux
的区别?
答案
名称 | 主要作用 | 特点/优势 | 典型场景 |
---|---|---|---|
redux | 状态管理核心库 | 单向数据流、纯函数 reducer | JS/React全家桶 |
@reduxjs/toolkit | redux 官方推荐工具集 | 简化配置、内置不可变处理,集成 immer | 快速开发、减少样板 |
react-redux | React 绑定库 | 提供 Provider、connect 等 | React组件状态同步 |
- redux:最基础的状态管理库,核心概念包括 store、action、reducer。所有状态变更需通过 action 派发,reducer 纯函数处理,强调可预测性和单向数据流。原生 API 较为底层,实际开发常需大量样板代码。
- @reduxjs/toolkit:官方推荐的 redux 工具集,封装了 createSlice、configureStore 等 API,自动处理不可变数据(基于 immer),内置 thunk 中间件,极大简化 reducer、action 创建和异步逻辑。适合现代 React 项目,减少冗余代码。
- react-redux:专为 React 设计的绑定库,提供
<Provider>
组件注入 store,connect
高阶组件和useSelector
、useDispatch
等 hooks,方便 React 组件访问和操作 redux 状态。实现组件与 store 的高效同步和订阅。内部依托于 react 提供的 useSyncExternalStoreWithSelector 实现外部状态绑定视图
延伸阅读
redux 是如何实现中间件机制的?
答案
Redux 本质是实现了函数组合的功能,通过将多个中间件函数组合成一个新的函数,从而实现对 dispatch 函数的增强。中间件可以在 action 被发送到 reducer 之前进行处理,比如记录日志、发送网络请求等。核心原理代码如下
// 实现代码组合
function compose(...funcs: Function[]) {
if (funcs.length === 0) {
// infer the argument type so it is usable in inference down the line
return <T>(arg: T) => arg
}
if (funcs.length === 1) {
return funcs[0]
}
return funcs.reduce(
(a, b) =>
(...args: any) =>
a(b(...args))
)
}
// 利用 createStore enhance 创建中间件
function applyMiddleware(
...middlewares: Middleware[]
): StoreEnhancer<any> {
return createStore => (reducer, preloadedState) => {
const store = createStore(reducer, preloadedState)
let dispatch: Dispatch = () => {
throw new Error(
'Dispatching while constructing your middleware is not allowed. ' +
'Other middleware would not be applied to this dispatch.'
)
}
const middlewareAPI: MiddlewareAPI = {
getState: store.getState,
dispatch: (action, ...args) => dispatch(action, ...args)
}
const chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose<typeof dispatch>(...chain)(store.dispatch)
return {
...store,
dispatch
}
}
}
redux-thunk 是什么?
答案
是 redux 的插件,实现了异步 action 的处理。核心逻辑如下
function createThunkMiddleware<
State = any,
BasicAction extends Action = AnyAction,
ExtraThunkArg = undefined,
>(extraArgument?: ExtraThunkArg) {
// Standard Redux middleware definition pattern:
// See: https://redux.js.org/tutorials/fundamentals/part-4-store#writing-custom-middleware
const middleware: ThunkMiddleware<State, BasicAction, ExtraThunkArg> =
({ dispatch, getState }) =>
next =>
action => {
// The thunk middleware looks for any functions that were passed to `store.dispatch`.
// If this "action" is really a function, call it and return the result.
if (typeof action === 'function') {
// Inject the store's `dispatch` and `getState` methods, as well as any "extra arg"
return action(dispatch, getState, extraArgument)
}
// Otherwise, pass the action down the middleware chain as usual
return next(action)
}
return middleware
}
mobx 与 redux 的区别
答案
对比项 | Redux | MobX |
---|---|---|
状态变更 | 纯函数 reducer,需 dispatch | 直接修改,自动响应 |
数据流 | 单向数据流 | 响应式,自动追踪依赖 |
可变性 | 强制不可变 | 支持可变,自动追踪 |
- Redux 强调可预测性和单向数据流,所有状态变更必须通过 action 派发,reducer 纯函数处理,便于调试和回溯。适合大型、复杂项目,利于团队协作和状态追踪。
- MobX 基于响应式编程,状态声明为 observable,修改后自动通知依赖视图更新。无需手动派发,代码简洁,适合快速开发和中小型项目。
代码示例
// Redux 示例
const reducer = (state = { count: 0 }, action) => {
switch (action.type) {
case 'inc': return { count: state.count + 1 }
default: return state
}
}
// MobX 示例
import { makeAutoObservable } from 'mobx'
class Store {
count = 0
constructor() { makeAutoObservable(this) }
inc() { this.count++ }
}