Redux 是一个体小精悍的库,但它相关的内容和 API 都是精挑细选的,目的是衍生出丰富的工具集和可扩展的生态系统。社区已经创建了各种各样的有用的插件、库和工具。使用 Redux 时并不需要您非要使用这些插件,但是它们可以帮助您更容易地实现特性并解决应用程序中的问题。
如果需要关于 Redux 所有内容的列表,推荐移步至 Awesome Redux。它包含了示例、样板代码、中间件、工具库,还有很多其它相关内容。要想学习 React 和 Redux ,React/Redux Links 包含了教程和不少有用的资源,Redux Ecosystem Links 则列出了 许多 Redux 相关的库及插件。
本页将只列出由 Redux 维护者审查过的一部分内容。不要因此打消尝试其它工具的信心!整个生态发展得太快,我们没有足够的时间去关注所有内容。建议只把这些当作“内部推荐”,如果你使用 Redux 创建了很酷的内容,不要犹豫,马上发个 PR 吧。
reduxjs/react-redux
Redux 与 react 的官方绑定库,由 Redux 团队维护
angular-redux/ng-redux
Redux 与 Angular 1 的绑定库
angular-redux/store
Redux 与 Angular 2+ 的绑定库
ember-redux/ember-redux
Redux 与 Ember 的绑定库
glimmer-redux/glimmer-redux
Redux 绑定 Ember 的 Glimmer 组件引擎
tur-nr/polymer-redux
Redux 与 Polymer 的绑定库
lastmjs/redux-store-element Redux 与自定义组件的绑定库
ryo33/combineSectionReducers
combineReducers
的扩展版本,它允许将 state
作为第三个参数传递给所有的子 reducer。
KodersLab/topologically-combine-reducers
一种 combineReducers
变体,定义 reducer 之间的相互依赖用于调用排序和数据传递
var masterReducer = topologicallyCombineReducers(
{ auth, users, todos },
// 定义依赖树
{ auth: ['users'], todos: ['auth'] }
)
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']
})
omnidan/redux-undo
轻松为 reducer 实现 undo/redo 和 action 的历史记录功能。
omnidan/redux-ignore
通过数组或过滤器函数忽略 redux action
omnidan/redux-recycle
在某些 action 上重置 redux 状态
ForbesLindesay/redux-optimist
reducer 增强器,用于启用与类型无关的乐观更新
reduxactions/redux-actions
Redux 的 Flux 标准 action 实用程序。
const increment = createAction('INCREMENT')
const reducer = handleActions({ [increment]: (state, action) => state + 1 }, 0)
const store = createStore(reducer)
store.dispatch(increment())
BerkeleyTrue/redux-create-types
根据命名空间创建标准和异步 action type。
export const types = createTypes(
['openModal', createAsyncTypes('fetch')],
'app'
)
// { openModal : "app.openModal", fetch : { start : "app.fetch.start", complete: 'app.fetch.complete' } }
maxhallinan/kreighter
根据类型和预期字段生成 action creator
const formatTitle = (id, title) => ({
id,
title: toTitleCase(title)
})
const updateBazTitle = fromType('UPDATE_BAZ_TITLE', formatTitle)
updateBazTitle(1, 'foo bar baz')
// -> { type: 'UPDATE_BAZ_TITLE', id: 1, title: 'Foo Bar Baz', }
reduxjs/reselect
创建可组合的 memoized 选择器函数,以便从 store state 有效地导出数据
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
对于常见 selector 用例的 reselect 的抽象化
const getBarBaz = createSelector(
['foo.bar', 'baz'],
(bar, baz) => `${bar} ${baz}`
)
getBarBaz({ foo: { bar: 'a' }, baz: 'b' }) // "a b"
jprichardson/redux-watch
根据 key path 或 selector 监视状态更改
let w = watch(() => mySelector(store.getState()))
store.subscribe(
w((newVal, oldVal) => {
console.log(newval, oldVal)
})
)
ashaffer/redux-subscribe
集中订阅基于 path 的 state 更改
store.dispatch( subscribe("users.byId.abcd", "subscription1", () => {} );
tappleby/redux-batched-subscribe
可以取消订阅通知的 store 增强器
const debounceNotify = _.debounce(notify => notify())
const store = createStore(
reducer,
initialState,
batchedSubscribe(debounceNotify)
)
manaflair/redux-batch
store 增强器,允许 dispatch action 数组
const store = createStore(reducer, reduxBatch)
store.dispatch([{ type: 'INCREMENT' }, { type: 'INCREMENT' }])
laysent/redux-batch-actions-enhancer
store 增强器,接受批量 action
const store = createStore(reducer, initialState, batch().enhancer)
store.dispatch(createAction({ type: 'INCREMENT' }, { type: 'INCREMENT' }))
tshelburne/redux-batched-actions
处理批量 action 的高阶 reducer
const store = createStore(enableBatching(reducer), initialState)
store.dispatch(batchActions([{ type: 'INCREMENT' }, { type: 'INCREMENT' }]))
rt2zz/redux-persist
使用许多可扩展的选项,持久化和补充 Redux store。
const store = createStore(reducer, autoRehydrate())
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 = createStore(reducer, applyMiddleware(storageMiddleware))
redux-offline/redux-offline
用于 Offline-First 应用程序的持久 store ,支持积极的 UI 更新(optimistic UI)
const store = createStore(reducer, offline(offlineConfig))
store.dispatch({
type: 'FOLLOW_USER_REQUEST',
meta: { offline: { effect: {}, commit: {}, rollback: {} } }
})
facebook/immutable-js
Javascript 的不可变持久数据集合
const map1 = Map({ a: 1, b: 2, c: 3 })
const map2 = map1.set('b', 50)
map1.get('b') // 2
map2.get('b') // 50
rtfeldman/seamless-immutable
冻结的不可变数组/对象,向后兼容 JS
const array = Immutable(['totally', 'immutable', { a: 42 }])
array[0] = 'edited' // does nothing
planttheidea/crio
具有 API 的不可变 JS 对象
const foo = crio(['foo'])
const fooBar = foo.push('bar') // new array: ['foo', 'bar']
aearly/icepick
用于将冻结的 JS 对象视为持久不可变集合的实用程序。
const newObj = icepick.assocIn({ c: { d: 'bar' } }, ['c', 'd'], 'baz')
const obj3 = icepicke.merge(obj1, obj2)
mweststrate/immer
运用代理使用普通的更新代码进行不可变更新
const nextState = produce(baseState, draftState => {
draftState.push({ todo: 'Tweet about it' })
draftState[1].done = true
})
kolodny/immutability-helper
react-addons-update 的直接替代品
const newData = update(myData, {
x: { y: { z: { $set: 7 } } },
a: { b: { $push: [9] } }
})
mariocasciaro/object-path-immutable
更简单的替代 immutability-helpers 和 Immutable.js 的库
const newObj = immutable(obj)
.set('a.b', 'f')
.del(['a', 'c', 0])
.value()
debitoor/dot-prop-immutable
dot-prop 库的不可变(Immutable)版本,带有一些扩展
const newState = dotProp.set(state, `todos.${index}.complete`, true)
const endOfArray = dotProp.get(obj, 'foo.$end')
gajus/redux-immutable
与 Immutable.js Maps 一起使用的 combineReducers 等价物
const initialState = Immutable.Map()
const rootReducer = combineReducers({})
const store = createStore(rootReducer, initialState)
eadmundo/redux-seamless-immutable
与 combineReducers 等效,与 seamless-immutable value 一起使用
import { combineReducers } from 'redux-seamless-immutable';
const rootReducer = combineReducers({ userReducer, posts
gaearon/redux-thunk
调度(dispatch)函数,调用并将 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});
}
}
}
redux-saga/redux-saga
使用同步查找生成器函数处理异步逻辑。 Sagas 返回 effect 的描述, 这些 effect 由 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
使用称为 “epics” 的 RxJS 可观察链处理异步逻辑。 撰写和取消异步操作以创建副作用等。
适用于: 复杂的异步逻辑,解耦的工作流程
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 返回它们来自然而纯粹地对您的 effect 进行排序。 reducer 现在返回状态值和副作用描述。
适用于: 试图尽可能地像 Elm 一样使用 Redux + JS
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
}
}
使用 observable 构建的副作用 lib,但允许使用回调、promises、async/await 或 observables。 提供 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)
}
})
acdlite/redux-promise
调度(Dispatch) promise 作为 action 的有效负载,并在 promise resolve 或 reject 时调度 FSA 兼容(FSA-compliant)的 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)功能。
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 获取数据并调度(dispatch)启动 / 成功 / 失败 action。
export const loadCategories() => ({ type: 'LOAD', payload: { request : { url: '/categories'} } });
agraboso/redux-api-middleware
通过读取 API 调用 action、获取数据和调度 FSA
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 = createStore(reducer, applyMiddleware(socketIoMiddleware))
store.dispatch({ type: 'server/hello', data: 'Hello!' })
tiberiuc/redux-react-firebase
Firebase、React 和 Redux 之间的集成。
rt2zz/redux-action-buffer
将所有操作缓冲到队列中,直到满足断路器条件,此时释放队列
wyze/redux-debounce
符合 FSA 标准的 Redux 中间件可以实现 action 的防抖。
mathieudutour/redux-queue-offline
离线时将 action 加入队列,并在重新联机时 dispatch 它们。
rangle/redux-beacon
与任何分析服务集成,可以在离线时跟踪,并将分析逻辑与应用逻辑分离。
hyperlab/redux-insights
使用简单的 API 进行分析和跟踪,以编写自己的适配器
markdalgleish/redux-analytics
使用 meta 分析值监视 Flux 标准操作并处理它们
tommikaikkonen/redux-orm
一个简单的不可变 ORM,用于管理 Redux sotre 中的关系数据。
Versent/redux-crud
基于约定的 action 和 reducer,用于处理 CRUD 逻辑
kwelch/entities-reducer
处理 Normalizr 数据的高阶 reducer
amplitude/redux-query
声明与组件共存的数据依赖关系,在组件 mount 时运行查询、执行乐观更新以及使用 Redux action 触发服务器更改。
cantierecreativo/redux-bees
声明性 JSON-API 交互,用于规范化数据,与可以运行查询的 React 高阶组件(HOC)交互
GetAmbassador/redux-clerk
具有规范化、乐观更新、同步/异步 action creator、 selector 和可扩展 reducer 的异步 CRUD 处理。
shoutem/redux-io
具有异步 CRUD、规范化、乐观更新、缓存、数据状态和错误处理的 JSON-API 抽象。
jmeas/redux-resource
用于管理“资源”的小而强大的系统:持久存储到远程服务器的数据。
tonyhb/redux-ui
用于 UI state 的“块级范围”。 装饰组件以声明数据字段,使这些数据字段成为 props 并可由嵌套子项更新。
@ui({
key: 'some-name',
state: { uiVar1: '', uiVar2: (props, state) => state.someValue },
reducer: (state, action) => {}
})
class YourComponent extends React.Component {}
threepointone/redux-react-local
Redux 中的本地组件 state,用于处理组件 action
@local({
ident: 'counter', initial: 0, reducer : (state, action) => action.me ? state + 1 : state }
})
class Counter extends React.Component {
epeli/lean-redux
使 Redux 中的组件的 state 与 setState 一样简单
const DynamicCounters = connectLean(
scope: "dynamicCounters",
getInitialState() => ({counterCount : 1}),
addCounter, removeCounter
)(CounterList);
ioof-holdings/redux-subspace
为分离的微前端创建独立的 “sub-store”,集成了 React、sagas 和 observables
const reducer = combineReducers({
subApp1: namespaced('subApp1')(counter),
subApp2: namespaced('subApp2')(counter)
})
const subApp1Store = subspace(state => state.subApp1, 'subApp1')(store)
const subApp2Store = subspace(state => state.subApp2, 'subApp2')(store)
subApp1Store.dispatch({ type: 'INCREMENT' })
console.log('store state:', store.getState()) // { "subApp1": { value: 2 }, "subApp2": { value: 1 } }
DataDog/redux-doghouse
旨在通过将 actIon 和 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 实现,专为在应用程序内显示 state 和 time-travel 调试而构建
zalmoxisus/redux-devtools-extension
Mihail Diordiev 的浏览器扩展,捆绑了多个 state 监视器视图,并增加了与浏览器自己的开发工具的集成
用于检查 React 和 React Native 应用程序的跨平台 Electron 应用程序,包括应用程序状态、API 请求、性能、错误、saga 和操作调度。
Log Monitor
Redux DevTools 默认监视器,提供树状视图
Dock Monitor
Redux DevTools 监视器的可调整大小和可移动的底座
Slider Monitor
Redux DevTools 的自定义监视器,用于重放录制的 Redux 操作
Inspector
Redux DevTools 的自定义监视器,可让您过滤操作,检查差异,并在状态中固定深层路径以观察其更改
Diff Monitor
Redux DevTools 的监视器,用于在 action 之间区分 Redux store 突变
Filterable Log Monitor
树状可筛选视图的 Redux DevTools 监视器
Chart Monitor
Redux DevTools 的图表监视器
Filter Actions
Redux DevTools 可组合监视器,具有过滤 action 的能力
evgenyrodionov/redux-logger
记录显示 action、state 和差异的中间件
inakianduaga/redux-state-history
提供 time-travel 和高效的 action 录制功能,包括导入 / 导出 action 日志和 action 播放的增强器。
joshwcomeau/redux-vcr
实时记录和重播用户会话
socialtables/redux-unhandled-action
在开发中对改变 state 的 action 发出警告
leoasis/redux-immutable-state-invariant
当您尝试在调度(dispatch)内或调度(dispatch)之间改变状态时抛出错误的中间件。
flexport/mutation-sentinel
帮助您在运行时深入检测突变并在代码库中强制实现不变性(immutability)。
mmahalwy/redux-pure-connect
检查并记录 react-redux 的 connect 方法是否通过 mapState
函数创建了不纯的 props。
arnaudbenard/redux-mock-store
一个模拟 store,用于将 dispatched action 保存在数组中以进行断言
Workable/redux-test-belt
扩展 store API 以使其更容易断言、隔离和操纵 store
conorhastings/redux-test-recorder
根据应用程序中的操作自动生成 Reducer 测试的中间件
wix/redux-testkit
用于测试 Redux 项目的完整且固定的测试工具包(Reducer、selectors、actions、thunk)
jfairbank/redux-saga-test-plan
使 saga 的集成和单元测试变得轻而易举
ReactTraining/react-router-redux
保持 state 与路由同步
FormidableLabs/redux-little-router
Redux 应用程序的一个小型路由,可以与 URL 进行通信
faceyspacey/redux-first-router
无缝 Redux-first 路由。 在 state 中考虑您的应用,而不是在路由或组件中,同时保持与地址栏同步。 一切都是 state。 连接您的组件,只需调度(dispatch)标准的 action。
erikras/redux-form
一个功能齐全的库,可以使 React HTML 表单在 Redux 中存储其状态。
davidkpiano/react-redux-form
React Redux Form 是一个 reducer creator 和 action creator 的集合,它们使 React 和 Redux 可以简单而高效地实现最复杂和自定义的 form。
keajs/kea
Redux、Redux-Saga 和 Reselect 的抽象。 为您的应用程序的 action、reducer、selector 和 saga 提供框架。 它赋予 Redux 权限,使其与 setState 一样简单。 它减少了样板和冗余,同时保持了可组合性。
jumpsuit/jumpstate
基于 Redux 的简化版本。 没有 action creator 或显式调度(dispatch),具有内置的简单副作用(side effect)系统。
TheComfyChair/redux-scc
采用定义的结构并使用“行为”来创建一组 actions、reducer responses 和 selectors。
Bloomca/redux-tiles
在 Redux 之上提供最小的抽象,以实现轻松的可组合性、简单的异步请求和可靠的可测试性。
Flux Standard Action
Flux action object 的人性化标准
Canonical Reducer Composition
嵌套 reducer 组合的固定标准
Ducks: Redux Reducer Bundles
捆绑 reducer、action type 和 action 的提议