从 redux 更改为 redux 工具包

IT技术 javascript reactjs typescript react-redux redux-toolkit
2021-04-06 22:12:21

Reactjs 新手,尝试通过编码学习,我需要一些代码帮助/建议,将这个 Redux 商店转换为 Redux 工具包,这里我使用名为 configureStore 的函数,有什么好方法可以将其更改为使用“configureStore” ' 来自 '@reduxjs/toolkit' 这是为了学习目的,'createRootReducer' 来自我的 reducers.js,它结合了

const createRootReducer = (history) => combineReducers({
    articles: articlesReducer,
    selection: selectionReducer,
});

将不胜感激任何帮助/建议。我的 store.js:

import { createBrowserHistory } from "history";
import { createStore, compose, applyMiddleware } from "redux";
import thunk from "redux-thunk";
import { routerMiddleware } from "connected-react-router";
import createRootReducer from "./reducers";

export const history = createBrowserHistory();

const storeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

export default function configureStore(preloadedState) {
  const store = createStore(
    createRootReducer(history),
    preloadedState,
    storeEnhancers(applyMiddleware(routerMiddleware(history), thunk))
  );
  return store;
}

1个回答

提前注意:

有一个与connected-react-router.

为了让您的设置正常工作,请确保安装history v4.10.1- 较新的版本会导致错误:

https://github.com/supasate/connected-react-router/issues/312#issuecomment-647082777


1. 中间件更新

redux-dev-toolsredux-thunk已经包含在终极版的工具包。

如果您需要导入额外的中间件,您可以使用getDefaultMiddleware.

如果您想添加一些自定义中间件,但仍希望添加默认中间件,则 getDefaultMiddleware 很有用:

因此,考虑到这一点,您可以redux-thunkpackage.json.


2. 移除redux进口

您不再需要 import createStore, compose, applyMiddleware, combineReducersfrom redux所有这些都是中内部处理configureStore提供API @reduxjs/toolkit

您也可以reduxpackage.json.


3. 将 args 应用到configureStorefrom @reduxjs/toolkit


更新后的商店可能如下所示:

// IMPORTANT: be sure to install history v4.10.1
// see open issue: https://github.com/supasate/connected-react-router/issues/312#issuecomment-647082777
import { createBrowserHistory, History } from "history";
import { configureStore } from "@reduxjs/toolkit";
import {
  routerMiddleware,
  connectRouter,
  RouterState
} from "connected-react-router";
import selectionReducer from "./reducers/selection";
import articlesReducer from "./reducers/articles";
import todosReducer, { I_TodoState } from "./reducers/todos";

export const history = createBrowserHistory();

// combineReducers will be handled internally by configureStore
const rootReducer = (history: History<any>) => ({
  articles: articlesReducer,
  selection: selectionReducer,
  todos: todosReducer,
  router: connectRouter(history)
});

const preloadedState = {};
export const store = configureStore({
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware().concat(routerMiddleware(history)),
  reducer: rootReducer(history),

  preloadedState
});

如果您将对象传递给reducer参数 in configureStore,则减速器将被组合。所以你不再需要做一个rootReducerwithcombineReducers


这是一个演示链接


更新

我想指出,从您最初的帖子中,您似乎只有 3 个中间件:

__REDUX_DEVTOOLS_EXTENSION_COMPOSE__thunk、 和routerMiddleware

您看到的错误发生是因为@redux/toolkit它为正确的不变性和状态的序列化提供了额外的保护。它通过包含redux-immutable-state-invariant在其默认中间件中来实现。

您之前的设置没有此中间件,这就是您现在只看到这些错误的原因。如果您已redux-immutable-state-invariant安装,您会在之前的设置中看到这些错误。

要实现与之前相同的设置,您不需要包含defaultMiddleware,但是通过您的减速器并了解为什么您的状态不是不可变和/或可序列化,这将是一个非常好的主意。

这是一个与你之前相同的设置,只有 @redux/toolkit

import { configureStore } from '@reduxjs/toolkit';
import { routerMiddleware, connectRouter } from 'connected-react-router';
import { createBrowserHistory } from 'history';
import thunk from 'redux-thunk';
import { rootReducer } from './reducer';

export const history = createBrowserHistory();

// combineReducers will be handled internally by configureStore
const rootReducer = (history) => ({
  articles: articlesReducer,
  selection: selectionReducer,
  router: connectRouter(history)
});

const preloadedState = {};
export const store = configureStore({
  middleware: [thunk, routerMiddleware(history)],
  reducer: rootReducer(history),
  preloadedState,
});

看起来开发工具已经配置好了:https://redux-toolkit.js.org/usage/usage-guide#store-setup,所以我没有在这里添加它们。您应该仍然可以在浏览器的开发人员工具中使用它们。

您应该研究为什么您当前的状态不是不可变/可序列化的。您的状态中可能存在循环引用,或者您的状态在某处直接发生变异。这可能会导致一些令人讨厌的错误,因为 redux 只有在状态不可变的情况下才真正有效。

但是,您仍然可以在当前设置中使用 @redux/toolkit。

现有的 reducer 和操作与 redux 工具包一起使用。您发布的错误表明状态正在发生变化。错误是从immutableStateInvariantMiddleware. 也许您的状态中有循环引用导致中间件中的无限递归。如果没有看到您的代码库,我很难判断。您可以尝试通过更改getDefaultMiddleware()为 来查看错误是否消失getDefaultMiddleware({ immutableCheck: false })如果它确实消失了,那么您应该检查并查看状态在哪里发生变异。Redux 状态应该始终是不可变的。
2021-05-30 22:12:21
我用这个解决了这些错误:export const store = configureStore({ middleware: (getDefaultMiddleware) => getDefaultMiddleware({ immutableCheck: false, serializableCheck: false, }).concat(routerMiddleware(history)), reducer: rootReducer(history),预加载状态,}); 但这不是正确的方法,有没有一种好方法可以快速检查状态在哪里发生变异,这样我就可以真正摆脱这些?
2021-06-17 22:12:21
它也给出:在一个动作中检测到​​一个不可序列化的值,在路径中:payload值:查看调度此操作的逻辑:{type: 'GET_FLOORPLAN', payload: img}(请参阅redux.js.org/faq/...)(要允许不可序列化的值,请参阅:redux-toolkit.js .org/usage/…
2021-06-18 22:12:21
我的减速器和动作是用旧的 redux 风格编码的,而不是 redux 工具包,当我将商店转换为使用 redux 工具包时,它可以保持这种状态吗?
2021-06-20 22:12:21
我完全按照你说的做了,但是出现了新的错误:1:redux-toolkit.esm.js:301 Uncaught (in promise) RangeError: Maximum call stack size exceeded at trackProperties (redux-toolkit.esm.js:301)在 trackProperties (redux-toolkit.esm.js:312) 2: Uncaught RangeError: 在 trackProperties (redux-toolkit.esm.js:301) 超过最大调用堆栈大小在 trackProperties (redux-toolkit.esm.js:312)
2021-06-21 22:12:21