如何解决此 ReferenceError: Cannot access 'authSlice' before初始化?

问题描述 投票:0回答:3

我在使用 React 和 Redux 时遇到问题,问题是这样的:

The problem

我收到错误:

ReferenceError:初始化前无法访问“authSlice”

我认为问题是我有一个名为http的类,我在那里导入store,然后在我的切片类中导入一个http方法,我想就是这样。但因为我需要访问商店,所以我附上我的商店、段和http类:

import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import { HOST } from "../http/utils";
import makeApiCall from "../http"; //Possible cause

const accessToken = localStorage.getItem("accessToken");
const refreshToken = localStorage.getItem("refreshToken");
const username = localStorage.getItem("username");

const initialState = {
  username: username || null,
  password: null,
  isLoading: false,
  error: null,
  accessToken: accessToken || null,
  refreshToken: refreshToken || null,
};

export const loginUser = createAsyncThunk(
  "api/login",
  async (payload, { rejectWithValue }) => {
    const url = HOST.concat("api/token/");
    return makeApiCall(url, "POST", payload, rejectWithValue);
  },
);

export const authSlice = createSlice({
  name: "auth",
  initialState,
  reducers: {
    logout: (state) => {
      state.accessToken = null;
      state.refreshToken = null;
      state.username = null;
      state.password = null;
      localStorage.removeItem("accessToken");
      localStorage.removeItem("refreshToken");
    },
    refresh: (state, action) => {
      state.refreshToken = action.payload.refresh;
      state.accessToken = action.payload.access;
    },
    setError: (state, action) => {
      state.error = action.payload;
      state.isLoading = false;
    },
  },
  extraReducers: (builder) => {
    builder
      .addCase(loginUser.pending, (state, action) => {
        state.isLoading = true;
      })
      .addCase(loginUser.fulfilled, (state, action) => {
        state.accessToken = action.payload.access;
        state.refreshToken = action.payload.refresh;
        localStorage.setItem("accessToken", state.accessToken);
        localStorage.setItem("refreshToken", state.refreshToken);
        state.isLoading = false;
      })
      .addCase(loginUser.rejected, (state, action) => {
        state.error = action.payload;
        state.isLoading = false;
      });
  },
});

export const { logout, setError, refresh } = authSlice.actions;
export default authSlice.reducer;


这是我的商店配置:

import { configureStore } from "@reduxjs/toolkit";
import { authSlice } from "./authSlice";
import { userSlice } from "./userSlice";

export const store = configureStore({
  reducer: {
    auth: authSlice.reducer,
    user: userSlice.reducer,
  },
});

这是我的班级http:

import axios from "axios";
import { store } from "../redux/store"; //Possible cause
import { HOST } from "./utils";

const getHeaders = () => {
  const headers = {
    Accept: "application/json",
    "Content-type": "Application/json",
  };
  const access = store.getState().auth.accessToken;
  if (access) {
    headers.Authorization = `Bearer ${access}`;
  }
  return headers;
};

const refreshAccessToken = async function () {
  return axios
    .request({
      method: "POST",
      url: HOST.concat("/api/v1/auth/refresh/"),
      data: {
        refresh: store.getState().auth.refreshToken,
      },
    })
    .then((response) => {
      if (response.status === 200) {
        store.dispatch({
          type: "auth/refresh",
          payload: response.data,
        });
      }
    })
    .catch(() => {
      store.dispatch({
        type: "auth/logout",
      });
    });
};

const axiosClient = axios.create();

axiosClient.interceptors.request.use(
  async (config) => {
    config.headers = getHeaders();
    return config;
  },
  (error) => {
    return Promise.reject(error);
  },
);

axiosClient.interceptors.response.use(
  (response) => {
    return response;
  },
  async function (error) {
    let response_status;
    try {
      response_status = error.response.status;
    } catch (e) {
      response_status = 200;
    }
    const originalRequest = error.config;
    if (response_status === 401 && !originalRequest._retry) {
      originalRequest._retry = true;
      await refreshAccessToken();
      return axiosClient(originalRequest);
    }

    return Promise.reject(error);
  },
);

export default async function makeApiCall(url, method, data, rejectWithValue) {
  return new Promise((resolve, reject) => {
    axiosClient
      .request({
        url,
        method,
        data,
      })
      .then((response) => {
        resolve(response.data);
      })
      .catch((error) => {
        reject(rejectWithValue(error.response.data));
      });
  });
}
javascript redux circular-dependency
3个回答
1
投票

这3个文件之间的循环依赖导致的错误

store
进口
segment
->
segment
进口
http
->
http
进口
store

解决此问题的一种方法是使

axios
初始化成为一个以
store
作为参数的函数,并在其他地方而不是在
http

内部调用它

这样你的

http
就与
store

脱钩了

0
投票

store
的实现与对
http
的呼吁分开。这是由于循环依赖造成的,在应用程序中保留循环依赖并不是一个好习惯。


0
投票

我认为你必须用

App
 包裹 
Provider

© www.soinside.com 2019 - 2024. All rights reserved.