basereducer is not a function – Redux Toolkit with createasyncthunk

huangapple go评论67阅读模式
英文:

basereducer is not a function - Redux Toolkit with createasyncthunk

问题

我正在使用redux-toolkit从MSAL获取accessToken,并使用redux-persist将存储在localStorage中。我在客户端列表页面获取搜索结果。当我刷新页面时,一切都正常工作。但几分钟前,它抛出了一个错误:"Error in function eval in ./node_modules/redux-persist/es/persistReducer.js:144 baseReducer is not a function",我无法确定我在哪里出错。

以下是一些代码示例:

store.js

import { configureStore } from '@reduxjs/toolkit';
import usersReducer from "./userSlice";
import storage from 'redux-persist/lib/storage';
import { persistReducer, persistStore } from 'redux-persist';

const persistConfig = { key: 'root', storage };
const persistedReducer = persistReducer(persistConfig, usersReducer);

export const store = configureStore({
  reducer: {
    users: persistedReducer,
  },
});

export const persistor = persistStore(store);

userSlice.js

import { useMsal } from "@azure/msal-react";
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import { loginRequest } from "./authConfig";
import { msalInstance } from "./pages/index";

// ...其他部分...

export default usersSlice.reducer;

index.js

import React from "react";
import { Provider, useDispatch } from "react-redux";
import { persistor, store } from "../../store";
import Footer from "../Footer";
import { createTheme, ThemeProvider } from "@mui/material/styles";
import { PersistGate } from 'redux-persist/integration/react';

// ...其他部分...

export default Layout;

LandingPage.js(在这里我正在分发动作)

const request = {
  ...loginRequest,
  account: accounts[0],
};
store.dispatch(fetchUsersToken(request));

index.js(在这里初始化msalInstance)

import React from "react";
import { Helmet } from "react-helmet";
import { PublicClientApplication } from "@azure/msal-browser";
import { MsalProvider, useMsal } from "@azure/msal-react";
import { loginRequest, msalConfig } from "../authConfig";
import PageLayout from "../components/PageLayout";
import App from "./app";
import Layout from "../components/Layout";

// ...其他部分...

export default function Home() {
  return (
    <>
      <Helmet>
        <title>Client Engagement Lookup</title>
      </Helmet>
      <MsalProvider instance={msalInstance}>
        <Layout>
          <PageLayout />
        </Layout>
      </MsalProvider>
    </>
  );
}

希望这些信息对你有所帮助。如果你需要更多的帮助,请随时告诉我。

英文:

I am using redux-toolkit to acquire accessToken from MSAL and redux-persist to persist the store in localStorage. I'm getting search results in clientlisting page. When I refresh the page it was working fine. But few minutes ago it throws me an error "Error in function eval in ./node_modules/redux-persist/es/persistReducer.js:144 baseReducer is not a function" I couldn't figure where am I doing wrong

store.js

import { configureStore } from &#39;@reduxjs/toolkit&#39;
import usersReducer from &quot;./userSlice&quot;;
import storage from &#39;redux-persist/lib/storage&#39;;
import { persistReducer, persistStore } from &#39;redux-persist&#39;;
const persistConfig = { key: &#39;root&#39;, storage, }
const persistedReducer = persistReducer(persistConfig, usersReducer)
export const store = configureStore(
  { 
    reducer: { 
      users: persistedReducer,
    }
  })
export const persistor = persistStore(store)

userSlice.js

import { useMsal } from &quot;@azure/msal-react&quot;;
import { createAsyncThunk, createSlice } from &quot;@reduxjs/toolkit&quot;;
import { loginRequest } from &quot;./authConfig&quot;;
import { msalInstance } from &quot;./pages/index&quot;;

export const fetchUsersToken = createAsyncThunk(
  &quot;users/fetchUsersToken&quot;,
  async (dispatch, getState) =&gt; {
    try {
      const token = await msalInstance.acquireTokenSilent(dispatch)
        .then((data) =&gt; data.accessToken)
      return token
    } catch (error) {
      return error.response.data
    }
  }
);

const usersSlice = createSlice({
  name: &quot;users&quot;,
  initialState: {
    users: null,
    loading: true
  },
  reducers: {},
  extraReducers(builder) {
    builder
      .addCase(fetchUsersToken.pending, (state, action) =&gt; {
        state.loading = true
      })
      .addCase(fetchUsersToken.fulfilled, (state, action) =&gt; {
        state.loading = false,
        state.users = action.payload
      })
      .addCase(fetchUsersToken.rejected, (state, action) =&gt; {
        state.loading = false

      });
  }
})

export default usersSlice.reducer;

index.js

import React from &quot;react&quot;
import { Provider, useDispatch } from &quot;react-redux&quot;;
import {persistor, store} from &quot;../../store&quot;;
import Footer from &quot;../Footer&quot;
import { createTheme, ThemeProvider } from &quot;@mui/material/styles&quot;
import { PersistGate } from &#39;redux-persist/integration/react&#39;;
// Global styles and component-specific styles.

//For changing default blue color for mui text-fields
const theme = createTheme({
  palette: {
    primary: { main: &quot;#000000&quot; },
  },
})

const Layout = ({ children }) =&gt; (
  &lt;div&gt;
    &lt;ThemeProvider theme={theme}&gt;
      &lt;Provider store={store}&gt;
        &lt;PersistGate loading={null} persistor={persistor}&gt;
          {children}
          &lt;Footer/&gt;
        &lt;/PersistGate&gt;
      &lt;/Provider&gt;
    &lt;/ThemeProvider&gt;
  &lt;/div&gt;
)

export default Layout

LandingPage.js ( where I'm dispatching the action.)

const request = {
  ...loginRequest,
  account: accounts[0]
}
store.dispatch(fetchUsersToken(request))

Here is my index.js ( where msalInstance initiated )

import React from &quot;react&quot;
import { Helmet } from &quot;react-helmet&quot;
import { PublicClientApplication } from &quot;@azure/msal-browser&quot;
import { MsalProvider, useMsal } from &quot;@azure/msal-react&quot;
import { loginRequest, msalConfig } from &quot;../authConfig&quot;
import PageLayout from &quot;../components/PageLayout&quot;
import App from &quot;./app&quot;
import Layout from &quot;../components/Layout&quot;
//Redux
import { Provider, useDispatch } from &quot;react-redux&quot;;
import {store} from &quot;../store&quot;;
//Redux Ends here
export const msalInstance = new PublicClientApplication(msalConfig)
export default function Home() {
return (
&lt;&gt;
&lt;Helmet&gt;
&lt;title&gt;Client Engagement Lookup&lt;/title&gt;
&lt;/Helmet&gt;
&lt;MsalProvider instance={msalInstance}&gt;
{/* &lt;Provider store={store}&gt; */}
&lt;Layout&gt;
&lt;PageLayout /&gt;
&lt;/Layout&gt;
{/* &lt;/Provider&gt; */}
&lt;/MsalProvider&gt;
&lt;/&gt;
)

}

答案1

得分: 1

以下是您要翻译的部分:

"After copy/pasting the code you shared into a running codesandbox I wasn't able to reproduce the error you describe, but I do see some discrepancies in the code, specifically in the userSlice.js file.

The main discrepancy I see is that the thunk is incorrectly accessing the thunkAPI. createAsyncThunk payload creators do take two arguments, the first is the arg (e.g. the request object) that is passed to the function and the second is the thunkAPI object. Update the thunk to correctly destructure dispatch and getState from the thunkAPI object.

export const fetchUsersToken = createAsyncThunk(
  "users/fetchUsersToken",
  async (request, { dispatch, getState }) => { // <-- destructure thunkAPI
    try {
      const { accessToken } = await msalInstance.acquireTokenSilent(request);
      return accessToken;
    } catch (error) {
      return error.response.data;
    }
  }
);

A second discrepancy I noticed was in the fetchUsersToken.fulfilled reducer case where a Comma operator was used between the lines to set the loading and users states. This doesn't really affect much though since each operand mutates the state independently, but should still be fixed for readability's and maintenance's sake.

const usersSlice = createSlice({
  name: "users",
  initialState: {
    users: null,
    loading: true
  },
  extraReducers(builder) {
    builder
      .addCase(fetchUsersToken.pending, (state, action) => {
        state.loading = true;
      })
      .addCase(fetchUsersToken.fulfilled, (state, action) => {
        state.loading = false;        // <-- own line, expression
        state.users = action.payload; // <-- own line, expression
      })
      .addCase(fetchUsersToken.rejected, (state, action) => {
        state.loading = false;
      });
  }
});

export default usersSlice.reducer;
英文:

After copy/pasting the code you shared into a running codesandbox I wasn't able to reproduce the error you describe, but I do see some discrepancies in the code, specifically in the userSlice.js file.

The main discrepancy I see is that the thunk is incorrectly accessing the thunkAPI. createAsyncThunk payload creators do take two arguments, the first is the arg (e.g. the request object) that is passed to the function and the second is the thunkAPI object. Update the thunk to correctly destructure dispatch and getState from the thunkAPI object.

export const fetchUsersToken = createAsyncThunk(
  &quot;users/fetchUsersToken&quot;,
  async (request, { dispatch, getState }) =&gt; { // &lt;-- destructure thunkAPI
    try {
      const { accessToken } = await msalInstance.acquireTokenSilent(request);
      return accessToken;
    } catch (error) {
      return error.response.data;
    }
  }
);

A second discrepancy I noticed was in the fetchUsersToken.fulfilled reducer case where a Comma operator was used between the lines to set the loading and users states. This doesn't really effect much though since each operand mutates the state independently, but should still be fixed for readability's and maintenance's sake.

const usersSlice = createSlice({
  name: &quot;users&quot;,
  initialState: {
    users: null,
    loading: true
  },
  extraReducers(builder) {
    builder
      .addCase(fetchUsersToken.pending, (state, action) =&gt; {
        state.loading = true;
      })
      .addCase(fetchUsersToken.fulfilled, (state, action) =&gt; {
        state.loading = false;        // &lt;-- own line, expression
        state.users = action.payload; // &lt;-- own line, expression
      })
      .addCase(fetchUsersToken.rejected, (state, action) =&gt; {
        state.loading = false;
      });
  }
});

export default usersSlice.reducer;

basereducer is not a function – Redux Toolkit with createasyncthunk

huangapple
  • 本文由 发表于 2023年2月9日 01:11:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/75389334.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定