Next13 '使用MySQL AsyncThunk时,无法在初始化之前访问'slice'

rvpgvaaj  于 2023-10-18  发布在  Mysql
关注(0)|答案(1)|浏览(131)

我想从后端直接获取一些用户数据到redux中,为此,我使用了createAsyncThunk。我已经创建了slice,并在slice file using的AsyncThunk and added the extraReducers中创建了一个getUserData函数。 问题是,我需要dispatch函数,我想在从后端获得token后调度它,因为我需要将token发送回用户后端。但是,如果我在运行npm run build时在login函数中调用getUserData()`的调度,我会得到这个错误
预呈现页面“/login”时出错。阅读更多信息:

https://nextjs.org/docs/messages/prerender-error
ReferenceError: Cannot access 'slice' before initialization

我的文件结构看起来像这样:

存储区位于src目录之外。
我尝试在其他文件中调度getUserData()。如果我从应用程序中将其分配到主页中,当我运行npm run build时会出现此错误。

Collecting page data .ReferenceError: Cannot access 'user_slice' before initialization

我应该提到我还没有使用这个文件。我在next.config.ts中设置了一个从“/”到不同页面的重定向。
如果我在主layout或任何其他布局中调度它,我会直接将此错误发送到浏览器。

Error: Cannot access '__WEBPACK_DEFAULT_EXPORT__' before initialization
src\store\createStore.ts (33:11) @ userSlice

  31 | authSlice,
  32 | modalSlice,
> 33 | userSlice,
     |         ^
  34 | currencySlice,
  35 | });
  36 |

但如果我派遣的功能内的商店页面工作正常.但是在那里分派函数是没有意义的。
我甚至创建了一个codesandbox,并添加了所有文件。我还删除了很多东西来管理,使应用程序在codesandbox和一些敏感的代码中工作。有趣的是,在codesandbox内部,构建工作正常。这里是codesandbox(如果应用程序不为您运行,请转到终端用户ctrl + cnpm run dev).
我不知道为什么它在商店页面内工作正常,但在登录页面上却不行,也不知道为什么它在codesandbox内工作正常。有人能帮帮忙吗
店铺代码:

import { combineReducers } from 'redux';
import { configureStore } from '@reduxjs/toolkit';
import { persistStore, persistReducer } from 'redux-persist';
import createWebStorage from 'redux-persist/lib/storage/createWebStorage';

import authSlice from './auth/slice';
import modalSlice from './modal/slice';
import userSlice from './user/slice';
import currencySlice from './currency/slice';

const createNoopStorage = () => {
  return {
    getItem(_key: any) {
      return Promise.resolve(null);
    },
    setItem(_key: any, value: any) {
      return Promise.resolve(value);
    },
    removeItem(_key: any) {
      return Promise.resolve();
    },
  };
};

const storage =
  typeof window !== 'undefined'
    ? createWebStorage('local')
    : createNoopStorage();

const rootReducer = combineReducers({
  authSlice,
  modalSlice,
  userSlice,
  currencySlice,
});

const persistConfig = {
  key: 'root',
  storage,
  whitelist: ['authSlice', 'userSlice'],
};

const persistedReducer = persistReducer(persistConfig, rootReducer);

export const store = configureStore({
  reducer: persistedReducer,
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware({
      serializableCheck: false,
    }),
});

export const persistor = persistStore(store);

export type RootState = ReturnType<typeof rootReducer>;
export type AppDispatch = ReturnType<typeof store.dispatch>;

Slice代码:

import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';

import { initialState } from './initialsState';
import { get } from '@/helpers/utils/fetch';

export const getUserData = createAsyncThunk('user/userData', async () => {
  try {
    return await get({ url: '/api/user' });
  } catch (error) {
    console.log('thunk user data error: ', error);
  }
});

const userSlice = createSlice({
  name: 'user',
  initialState,
  reducers: {
    clearUserData: (state) => {
      state.user = null;
    },
  },
  extraReducers: (builder) => {
    builder
      .addCase(getUserData.pending, (state) => {
        state.status = 'loading';
      })
      .addCase(getUserData.fulfilled, (state, action) => {
        state.status = 'success';
        state.user = action.payload;
      })
      .addCase(getUserData.rejected, (state, action) => {
        (state.status = 'failed'), (state.error = action.error.message);
      });
  },
});

export const { clearUserData } = userSlice.actions;

export default userSlice.reducer;

登录功能

const onLogin = async () => {
    setIsLoading(true);
    try {
      const response = await axiosInstance.post('/api/auth/login', userData);
      const token = response.data.accessTokens;

      dispatch(setToken(token));
      (dispatch as ThunkDispatch<RootState, void, AnyAction>)(getUserData());

      push(routes.shop);
      setError('');
      setIsLoading(false);
    } catch (error: any) {
      setIsLoading(false);
      if (error.response && error.response.status === 400) {
        setError('Incorrect credentials');
      } else {
        console.log('Login Error', error);
      }
    }
  };
vbopmzt1

vbopmzt11#

据我所知,看起来你的getUserData操作试图在示例化store之前关闭并使用store。创建store对象的文件从创建切片的文件导入。
getUserData操作应该使用传递给有效负载创建者的第二个参数,而不是导入store,例如。thunkAPI对象。
范例:

export const getUserData = createAsyncThunk(
  'user/userData',
  async (_, thunkApi) => {
    try {
      const userToken = userTokenSelector(thunkApi.getState());

      if (userToken) {
        console.log(userToken);
        return await get({ url: '/api/user' });
      }
    } catch (error) {
      console.log('thunk user data error: ', error);
      return thunkApi.rejectWithValue(error);
    }
  }
);

相关问题