本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →
生态系统
Redux 是一个小型库,但其契约和 API 经过精心设计,催生了一个工具和扩展的生态系统。社区创建了大量有用的附加组件、库和工具。使用 Redux 并不需要这些附加组件,但它们可以帮助你更轻松地实现功能并解决应用中的问题。
要查看与 Redux 相关的库、附加组件和工具的详尽目录,请查阅 Redux 生态系统链接列表。此外,React/Redux 链接列表包含了供学习 React 或 Redux 的教程和其他实用资源。
本页面列出了 Redux 维护者亲自审核或在社区中广泛采用的 Redux 相关附加组件。但这并不妨碍你尝试其他工具!生态系统发展太快,我们时间有限无法一一查看。请将这些视为"精选推荐",如果你用 Redux 构建了出色的项目,请随时提交 PR。
目录
库集成与绑定
reduxjs/react-redux
由 Redux 团队维护的官方 React 绑定
angular-redux/ng-redux
Angular 1 的 Redux 绑定
ember-redux/ember-redux
Ember 的 Redux 绑定
glimmer-redux/glimmer-redux
针对 Ember Glimmer 组件引擎的 Redux 绑定
tur-nr/polymer-redux
Polymer 的 Redux 绑定
lastmjs/redux-store-element 自定义元素的 Redux 绑定
Reducer
Reducer 组合
ryo33/combineSectionReducers
combineReducers 的扩展版本,允许将 state 作为第三个参数传递给所有切片 reducer
KodersLab/topologically-combine-reducers
支持定义跨切片依赖关系以实现顺序控制和数据传递的 combineReducers 变体
var masterReducer = topologicallyCombineReducers(
{ auth, users, todos },
// define the dependency tree
{ auth: ['users'], todos: ['auth'] }
)
Reducer 组合
acdlite/reduce-reducers
支持在同一层级对 reducer 进行顺序组合
const combinedReducer = combineReducers({ users, posts, comments })
const rootReducer = reduceReducers(combinedReducer, otherTopLevelFeatureReducer)
mhelmer/redux-xforms
可组合的 reducer 转换器集合
const createByFilter = (predicate, mapActionToKey) =>
compose(
withInitialState({}), // inject initial state as {}
withFilter(predicate), // let through if action has filterName
updateSlice(mapActionToKey), // update a single key in the state
isolateSlice(mapActionToKey) // run the reducer on a single state slice
)
adrienjt/redux-data-structures
针对常见数据结构(计数器、映射、列表/队列/栈、集合)的 reducer 工厂函数
const myCounter = counter({
incrementActionTypes: ['INCREMENT'],
decrementActionTypes: ['DECREMENT']
})
高阶 Reducer
omnidan/redux-undo
为 reducer 提供无痛撤销/重做和操作历史功能
omnidan/redux-ignore
通过数组或过滤函数忽略 redux 操作
omnidan/redux-recycle
在特定操作时重置 redux 状态
ForbesLindesay/redux-optimist
支持类型无关乐观更新的 reducer 增强器
工具集
reduxjs/reselect
创建可组合的记忆化选择器函数,用于高效派生 store 状态中的数据
const taxSelector = createSelector(
[subtotalSelector, taxPercentSelector],
(subtotal, taxPercent) => subtotal * (taxPercent / 100)
)
paularmstrong/normalizr
根据模式规范化嵌套 JSON 数据
const user = new schema.Entity('users')
const comment = new schema.Entity('comments', { commenter: user })
const article = new schema.Entity('articles', {
author: user,
comments: [comment]
})
const normalizedData = normalize(originalData, article)
planttheidea/selectorator
为常见选择器用例提供 Reselect 的抽象封装
const getBarBaz = createSelector(
['foo.bar', 'baz'],
(bar, baz) => `${bar} ${baz}`
)
getBarBaz({ foo: { bar: 'a' }, baz: 'b' }) // "a b"
Store
变更订阅
jprichardson/redux-watch
基于关键路径或选择器监听状态变更
let w = watch(() => mySelector(store.getState()))
store.subscribe(
w((newVal, oldVal) => {
console.log(newval, oldVal)
})
)
ashaffer/redux-subscribe
基于路径集中订阅状态变更
store.dispatch( subscribe("users.byId.abcd", "subscription1", () => {} );
批处理
tappleby/redux-batched-subscribe
可防抖订阅通知的 store 增强器
const debounceNotify = _.debounce(notify => notify())
const store = configureStore({
reducer,
enhancers: [batchedSubscribe(debounceNotify)]
})
manaflair/redux-batch
支持分发操作数组的 store 增强器
const store = configureStore({
reducer,
enhancers: existingEnhancersArray => [
reduxBatch,
...existingEnhancersArray,
reduxBatch
]
})
store.dispatch([{ type: 'INCREMENT' }, { type: 'INCREMENT' }])
laysent/redux-batch-actions-enhancer
接受批量操作的 store 增强器
const store = configureStore({ reducer, enhancers: [batch().enhancer] })
store.dispatch(createAction({ type: 'INCREMENT' }, { type: 'INCREMENT' }))
tshelburne/redux-batched-actions
处理批量操作的高阶 reducer
const store = configureStore({ reducer: enableBatching(rootReducer) })
store.dispatch(batchActions([{ type: 'INCREMENT' }, { type: 'INCREMENT' }]))
持久化
rt2zz/redux-persist
持久化和恢复 Redux store,提供丰富的可扩展选项
const persistConfig = { key: 'root', version: 1, storage }
const persistedReducer = persistReducer(persistConfig, rootReducer)
export const store = configureStore({
reducer: persistedReducer,
middleware: getDefaultMiddleware =>
getDefaultMiddleware({
serializableCheck: {
ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER]
}
})
})
export const persistor = persistStore(store)
react-stack/redux-storage
支持灵活后端的 Redux 持久化层
const reducer = storage.reducer(combineReducers(reducers))
const engine = createEngineLocalStorage('my-save-key')
const storageMiddleware = storage.createMiddleware(engine)
const store = configureStore({
reducer,
middleware: getDefaultMiddleware =>
getDefaultMiddleware.concat(storageMiddleware)
})
redux-offline/redux-offline
面向离线优先应用的持久化存储方案,支持乐观 UI 更新
const store = configureStore({ reducer, enhancer: [offline(offlineConfig)] })
store.dispatch({
type: 'FOLLOW_USER_REQUEST',
meta: { offline: { effect: {}, commit: {}, rollback: {} } }
})
不可变数据
ImmerJS/immer
使用代理(Proxy)实现常规可变语法编写不可变更新
const nextState = produce(baseState, draftState => {
draftState.push({ todo: 'Tweet about it' })
draftState[1].done = true
})
副作用处理
广泛使用的方案
reduxjs/redux-thunk
可派发函数(接收 dispatch 和 getState 作为参数),为 AJAX 调用和其他异步行为提供解决方案
最佳适用场景:入门学习、简单异步逻辑和复杂同步逻辑
function fetchData(someValue) {
return (dispatch, getState) => {
dispatch({type : "REQUEST_STARTED"});
myAjaxLib.post("/someEndpoint", {data : someValue})
.then(response => dispatch({type : "REQUEST_SUCCEEDED", payload : response})
.catch(error => dispatch({type : "REQUEST_FAILED", error : error});
};
}
function addTodosIfAllowed(todoText) {
return (dispatch, getState) => {
const state = getState();
if(state.todos.length < MAX_TODOS) {
dispatch({type : "ADD_TODO", text : todoText});
}
}
}
listenerMiddleware (Redux Toolkit)
listenerMiddleware 旨在成为 saga 和 observable 等主流 Redux 异步中间件的轻量级替代方案。虽然复杂度和概念与 thunk 相似,但能复现某些常见的 saga 使用模式
listenerMiddleware.startListening({
matcher: isAnyOf(action1, action2, action3),
effect: (action, listenerApi) => {
const user = selectUserDetails(listenerApi.getState())
const { specialData } = action.meta
analyticsApi.trackUsage(action.type, user, specialData)
}
})
redux-saga/redux-saga
使用类同步的生成器函数处理异步逻辑。Saga 返回副作用描述,由中间件执行,充当 JS 应用的"后台线程"
最佳适用场景:复杂异步逻辑、解耦工作流
function* fetchData(action) {
const { someValue } = action
try {
const response = yield call(myAjaxLib.post, '/someEndpoint', {
data: someValue
})
yield put({ type: 'REQUEST_SUCCEEDED', payload: response })
} catch (error) {
yield put({ type: 'REQUEST_FAILED', error: error })
}
}
function* addTodosIfAllowed(action) {
const { todoText } = action
const todos = yield select(state => state.todos)
if (todos.length < MAX_TODOS) {
yield put({ type: 'ADD_TODO', text: todoText })
}
}
redux-observable/redux-observable
使用 RxJS 可观察链(称为"epic")处理异步逻辑,支持组合和取消异步操作以创建副作用
最佳适用场景:复杂异步逻辑、解耦工作流
const loginRequestEpic = action$ =>
action$
.ofType(LOGIN_REQUEST)
.mergeMap(({ payload: { username, password } }) =>
Observable.from(postLogin(username, password))
.map(loginSuccess)
.catch(loginFailure)
)
const loginSuccessfulEpic = action$ =>
action$
.ofType(LOGIN_SUCCESS)
.delay(2000)
.mergeMap(({ payload: { msg } }) => showMessage(msg))
const rootEpic = combineEpics(loginRequestEpic, loginSuccessfulEpic)
将 Elm 架构移植到 Redux,允许通过 reducer 返回副作用实现自然纯函数式流程。现在 reducer 可同时返回状态值和副作用描述
最佳适用场景:在 Redux+JS 中最大程度模拟 Elm 开发模式
export const reducer = (state = {}, action) => {
switch (action.type) {
case ActionType.LOGIN_REQUEST:
const { username, password } = action.payload
return loop(
{ pending: true },
Effect.promise(loginPromise, username, password)
)
case ActionType.LOGIN_SUCCESS:
const { user, msg } = action.payload
return loop(
{ pending: false, user },
Effect.promise(delayMessagePromise, msg, 2000)
)
case ActionType.LOGIN_FAILURE:
return { pending: false, err: action.payload }
default:
return state
}
}
基于可观察对象构建的副作用库,支持回调、Promise、async/await 或可观察对象。提供声明式的 action 处理能力
最佳适用场景:高度解耦的异步逻辑
const loginLogic = createLogic({
type: Actions.LOGIN_REQUEST,
process({ getState, action }, dispatch, done) {
const { username, password } = action.payload
postLogin(username, password)
.then(
({ user, msg }) => {
dispatch(loginSucceeded(user))
setTimeout(() => dispatch(showMessage(msg)), 2000)
},
err => dispatch(loginFailure(err))
)
.then(done)
}
})
Promise 处理
acdlite/redux-promise
将 Promise 作为 action 有效载荷派发,在 Promise 解析/拒绝时派发符合 FSA 规范的 action
dispatch({ type: 'FETCH_DATA', payload: myAjaxLib.get('/data') })
// will dispatch either {type : "FETCH_DATA", payload : response} if resolved,
// or dispatch {type : "FETCH_DATA", payload : error, error : true} if rejected
lelandrichardson/redux-pack
基于约定的 Promise 处理方案,提供合理声明式实现,在不暴露完整派发能力的前提下引导良好实践
dispatch({type : "FETCH_DATA", payload : myAjaxLib.get("/data") });
// in a reducer:
case "FETCH_DATA": =
return handle(state, action, {
start: prevState => ({
...prevState,
isLoading: true,
fooError: null
}),
finish: prevState => ({ ...prevState, isLoading: false }),
failure: prevState => ({ ...prevState, fooError: payload }),
success: prevState => ({ ...prevState, foo: payload }),
});
中间件
网络与套接字
svrcekmichal/redux-axios-middleware
使用 Axios 获取数据,并派发开始/成功/失败 action
export const loadCategories() => ({ type: 'LOAD', payload: { request : { url: '/categories'} } });
agraboso/redux-api-middleware
读取 API 调用 action,执行请求并派发 FSA 规范 action
const fetchUsers = () => ({
[CALL_API]: {
endpoint: 'http://www.example.com/api/users',
method: 'GET',
types: ['REQUEST', 'SUCCESS', 'FAILURE']
}
})
itaylor/redux-socket.io
连接 socket.io 和 redux 的强约定方案
const store = configureStore({
reducer,
middleware: getDefaultMiddleware =>
getDefaultMiddleware.concat(socketIoMiddleware)
})
store.dispatch({ type: 'server/hello', data: 'Hello!' })
tiberiuc/redux-react-firebase
Firebase、React 与 Redux 的集成方案
异步行为处理
rt2zz/redux-action-buffer
将动作缓冲至队列,满足中断条件时释放队列
wyze/redux-debounce
符合 FSA 规范的 Redux 中间件,用于动作防抖
mathieudutour/redux-queue-offline
离线时缓存动作,网络恢复后自动派发
数据分析
rangle/redux-beacon
支持任意分析服务,具备离线追踪能力,解耦业务逻辑与分析逻辑
markdalgleish/redux-analytics
监听带有元分析值的 Flux 标准动作并处理
实体与集合管理
tommikaikkonen/redux-orm
简洁的不可变 ORM,用于管理 Redux 中的关系型数据
Versent/redux-crud
基于约定的 CRUD 动作与 reducer 实现
kwelch/entities-reducer
高阶 reducer,用于处理 Normalizr 标准化数据
amplitude/redux-query
声明组件数据依赖,支持挂载时查询、乐观更新,通过 Redux 动作触发服务变更
cantierecreativo/redux-bees
声明式 JSON-API 交互方案,支持数据标准化,提供可执行查询的 React HOC
GetAmbassador/redux-clerk
异步 CRUD 处理方案,包含标准化、乐观更新、同步/异步动作创建器、选择器和可扩展 reducer
shoutem/redux-io
JSON-API 抽象层,支持异步 CRUD、标准化、乐观更新、缓存、数据状态与错误处理
jmeas/redux-resource
轻量强大的资源管理系统,用于管理持久化到远程服务器的数据
组件状态与封装
threepointone/redux-react-local
在 Redux 中管理组件本地状态,支持组件动作处理
@local({
ident: 'counter', initial: 0, reducer : (state, action) => action.me ? state + 1 : state }
})
class Counter extends React.Component {
epeli/lean-redux
使 Redux 中的组件状态管理如同 setState 般简单
const DynamicCounters = connectLean(
scope: "dynamicCounters",
getInitialState() => ({counterCount : 1}),
addCounter, removeCounter
)(CounterList);
DataDog/redux-doghouse
通过限定动作和 reducer 到组件实例范围,简化可复用组件的 Redux 开发
const scopeableActions = new ScopedActionFactory(actionCreators)
const actionCreatorsScopedToA = scopeableActions.scope('a')
actionCreatorsScopedToA.foo('bar') //{ type: SET_FOO, value: 'bar', scopeID: 'a' }
const boundScopeableActions = bindScopedActionFactories(
scopeableActions,
store.dispatch
)
const scopedReducers = scopeReducers(reducers)
开发者工具
调试器与查看器
Dan Abramov 开发的官方 Redux DevTools,支持应用内状态展示和时间旅行调试
zalmoxisus/redux-devtools-extension
Mihail Diordiev 的浏览器扩展,集成了多种状态监控视图并与浏览器原生开发者工具深度整合
跨平台 Electron 应用,用于检查 React 和 React Native 应用,包括应用状态、API 请求、性能指标、错误信息、sagas 以及 action 派发过程
DevTools 监控面板
日志监控器
Redux DevTools 默认监控面板,提供树状视图展示
停靠监控器
可调整大小和移动位置的 Redux DevTools 监控面板停靠栏
滑动监控器
用于重放已录制 Redux actions 的自定义监控面板
差异监控器
可视化展示 actions 之间 Redux store 状态差异的监控面板
可过滤日志监控器
支持过滤功能的树状视图 Redux 监控面板
Action 过滤器
可组合的 Redux DevTools 监控面板,具备 actions 过滤能力
日志记录
redux-logger
展示 actions、状态及差异的日志记录中间件
redux-state-history
提供时间旅行和高效 action 录制能力的增强器,支持 action 日志导入/导出和回放
redux-vcr
实时录制和回放用户操作会话
redux-unhandled-action
开发环境下对未触发状态变更的 actions 发出警告
变更检测
redux-immutable-state-invariant
在 dispatch 过程中或 dispatch 之间检测到状态变更时抛出错误的中间件
mutation-sentinel
深度检测运行时数据变更,强制保持代码不可变性
mmahalwy/redux-pure-connect
检测并记录 react-redux 的 connect 方法是否传入了会产生非纯净属性的 mapState 函数
测试工具
redux-mock-store
模拟 store 将已派发的 actions 存入数组供断言使用
redux-test-belt
扩展 store API 以简化断言、隔离和操作 store
redux-test-recorder
根据应用内 actions 自动生成 reducer 测试的中间件
wix/redux-testkit
完整且开箱即用的测试套件,用于测试 Redux 项目(reducers、selectors、actions、thunks)
jfairbank/redux-saga-test-plan
让 saga 的集成测试和单元测试变得轻而易举
路由
supasate/connected-react-router 将 React Router v4+ 的状态与 Redux store 保持同步
faceyspacey/redux-first-router
无缝实现 Redux 优先的路由方案。以状态(而非路由或组件)的思维构建应用,同时保持地址栏同步。万物皆状态。连接组件并直接派发符合 flux 标准的 action
表单
erikras/redux-form
功能完备的库,支持将 React HTML 表单的状态存储在 Redux 中
davidkpiano/react-redux-form
提供 reducer 创建器和 action 创建器,即使是最复杂的自定义表单也能通过 React 和 Redux 简洁高效地实现
高层抽象
keajs/kea
基于 Redux、Redux-Saga 和 Reselect 的抽象层。为应用的 actions、reducers、selectors 和 sagas 提供框架,通过类似 setState 的简易 API 增强 Redux 能力。在保持组合性的同时减少样板代码和冗余
TheComfyChair/redux-scc
通过预定义结构和"行为模式"自动创建 actions、reducer 响应和 selectors 集合
Bloomca/redux-tiles
在 Redux 基础上提供最小抽象层,支持轻松组合、简化异步请求并提升可测试性
社区规范
Flux Standard Action
人性化的 Flux action 对象标准
Canonical Reducer Composition
关于嵌套 reducer 组合的权威标准
Ducks: Redux Reducer Bundles
将 reducers、action 类型和 actions 打包组织的提案方案