生态系统
Redux 是一个很小的库,但它的契约和 API 经过精心选择,可以产生一个工具和扩展的生态系统,社区创建了各种有用的附加组件、库和工具。您不需要使用任何这些附加组件来使用 Redux,但它们可以帮助您更轻松地实现功能并解决应用程序中的问题。
有关与 Redux 相关的库、附加组件和工具的广泛目录,请查看 Redux 生态系统链接 列表。此外,React/Redux 链接 列表包含教程和其他对学习 React 或 Redux 的任何人都有用的资源。
本页面列出了一些 Redux 维护者亲自审核过或在社区中得到广泛采用的 Redux 相关插件。但这并不意味着你不应该尝试其他插件!生态系统发展得太快,我们没有足够的时间去审查所有插件。可以将这些插件视为“精选推荐”,如果你用 Redux 构建了一些很棒的东西,请随时提交 PR。
目录
库集成和绑定
reduxjs/react-redux
Redux 的官方 React 绑定,由 Redux 团队维护
angular-redux/ng-redux
Angular 1 绑定到 Redux
ember-redux/ember-redux
Ember 绑定到 Redux
glimmer-redux/glimmer-redux
Ember 的 Glimmer 组件引擎的 Redux 绑定
tur-nr/polymer-redux
Redux 绑定到 Polymer
lastmjs/redux-store-element Redux 绑定到自定义元素
Reducers
Reducer 组合
ryo33/combineSectionReducers
combineReducers
的扩展版本,允许将 state
作为第三个参数传递给所有切片 reducers。
KodersLab/topologically-combine-reducers
combineReducers
的变体,允许定义跨切片依赖关系以进行排序和数据传递
var masterReducer = topologicallyCombineReducers(
{ auth, users, todos },
// define the dependency tree
{ auth: ['users'], todos: ['auth'] }
)
Reducer 组成
acdlite/reduce-reducers
提供相同级别上 reducers 的顺序组成
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
创建可组合的记忆化选择器函数,用于从存储状态中有效地派生数据
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"
存储
更改订阅
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
可以对订阅通知进行去抖动的存储增强器
const debounceNotify = _.debounce(notify => notify())
const store = configureStore({
reducer,
enhancers: [batchedSubscribe(debounceNotify)]
})
manaflair/redux-batch
允许调度操作数组的存储增强器
const store = configureStore({
reducer,
enhancers: existingEnhancersArray => [
reduxBatch,
...existingEnhancersArray,
reduxBatch
]
})
store.dispatch([{ type: 'INCREMENT' }, { type: 'INCREMENT' }])
laysent/redux-batch-actions-enhancer
接受批处理操作的存储增强器
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 存储,具有许多可扩展选项
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
使用代理,通过正常的可变代码进行不可变更新
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 旨在成为更广泛使用的 Redux 异步中间件(如 sagas 和 observables)的轻量级替代方案。虽然在复杂性和概念上类似于 thunks,但它可以用来复制一些常见的 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
使用同步外观的生成器函数处理异步逻辑。Sagas 返回效果的描述,这些效果由 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 返回它们来自然地、纯粹地对效果进行排序。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
}
}
使用 observables 构建的副作用库,但允许使用回调、promise、async/await 或 observables。提供对操作的声明式处理。
最适合:高度解耦的异步逻辑
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)
}
})
Promises
acdlite/redux-promise
将 promise 作为操作负载进行分派,并在 promise 解决或拒绝时分派符合 FSA 的操作。
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 }),
});
Middleware
网络和套接字
svrcekmichal/redux-axios-middleware
使用 Axios 获取数据并分派开始/成功/失败操作
export const loadCategories() => ({ type: 'LOAD', payload: { request : { url: '/categories'} } });
agraboso/redux-api-middleware
读取 API 调用操作,获取并分派 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 = 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
用于 Redux 的符合 FSA 的中间件,用于对操作进行去抖动。
mathieudutour/redux-queue-offline
在离线时排队操作,并在重新联机时分派它们。
分析
rangle/redux-beacon
与任何分析服务集成,可以在离线时跟踪,并将分析逻辑与应用程序逻辑分离
markdalgleish/redux-analytics
监视带有元分析值的 Flux 标准操作,并对其进行处理
实体和集合
tommikaikkonen/redux-orm
一个简单的不可变 ORM,用于在 Redux 存储中管理关系数据。
Versent/redux-crud
基于约定的操作和 reducer,用于 CRUD 逻辑
kwelch/entities-reducer
一个高阶 reducer,用于处理来自 Normalizr 的数据
amplitude/redux-query
在组件中声明共置数据依赖项,在组件挂载时运行查询,执行乐观更新,并使用 Redux 操作触发服务器更改。
cantierecreativo/redux-bees
声明式 JSON-API 交互,规范化数据,并提供一个可以运行查询的 React HOC
GetAmbassador/redux-clerk
带有规范化、乐观更新、同步/异步操作创建者、选择器和可扩展 reducer 的异步 CRUD 处理。
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 请求、性能、错误、saga 和操作调度。
DevTools 监视器
日志监视器
Redux DevTools 的默认监视器,具有树状视图
码头监视器
Redux DevTools 监控器的可调整大小和可移动停靠栏
滑块监控器
Redux DevTools 的自定义监控器,用于重播记录的 Redux 操作
差异监控器
Redux DevTools 的监控器,用于对操作之间 Redux 存储的变异进行差异比较
可过滤日志监控器
Redux DevTools 的可过滤树视图监控器
过滤操作
Redux DevTools 可组合监控器,具有过滤操作的功能
日志记录
evgenyrodionov/redux-logger
显示操作、状态和差异的日志记录中间件
inakianduaga/redux-state-history
增强器,提供时间旅行和高效的操作记录功能,包括操作日志的导入/导出和操作回放。
joshwcomeau/redux-vcr
实时录制和回放用户会话
socialtables/redux-unhandled-action
在开发中警告未产生状态更改的操作
变异检测
leoasis/redux-immutable-state-invariant
中间件,当您尝试在调度中或调度之间更改状态时抛出错误。
flexport/mutation-sentinel
帮助您在运行时深度检测变异,并在您的代码库中强制执行不变性。
mmahalwy/redux-pure-connect
检查并记录 react-redux 的 connect 方法是否传递了创建不纯属性的 mapState
函数。
测试
arnaudbenard/redux-mock-store
一个模拟存储,将已分派的 action 保存到数组中以进行断言
Workable/redux-test-belt
扩展存储 API,使其更容易断言、隔离和操作存储
conorhastings/redux-test-recorder
中间件,根据应用程序中的操作自动生成 reducer 测试
wix/redux-testkit
用于测试 Redux 项目(reducer、selector、action、thunk)的完整且有见地的测试工具包
jfairbank/redux-saga-test-plan
使 saga 的集成和单元测试变得轻而易举
路由
supasate/connected-react-router 将 React Router v4+ 状态与您的 Redux 存储同步。
faceyspacey/redux-first-router
无缝 Redux-first 路由。将您的应用程序视为状态,而不是路由或组件,同时保持地址栏同步。一切都是状态。连接您的组件并仅分派 Flux 标准操作。
表单
erikras/redux-form
一个功能齐全的库,用于启用 React HTML 表单以将其状态存储在 Redux 中。
davidkpiano/react-redux-form
React Redux Form 是一个 reducer 创建器和 action 创建器集合,它使使用 React 和 Redux 实现即使是最复杂和自定义的表单也变得简单高效。
高级抽象
keajs/kea
Redux、Redux-Saga 和 Reselect 之上的抽象。为您的应用程序的 action、reducer、selector 和 saga 提供框架。它增强了 Redux,使其使用起来与 setState 一样简单。它减少了样板代码和冗余,同时保留了可组合性。
TheComfyChair/redux-scc
采用定义的结构并使用“行为”来创建一组 action、reducer 响应和 selector。
Bloomca/redux-tiles
在 Redux 之上提供最小的抽象,以允许轻松组合、轻松异步请求和合理的测试能力。
社区惯例
Flux 标准操作
Flux 操作对象的友好标准
规范的 Reducer 组合
嵌套 reducer 组合的意见标准
Ducks:Redux Reducer 包
关于捆绑 reducer、action 类型和 action 的提案