본문 바로가기

A.개발관련자료

[React] redux-toolkit의 slice 비동기함수 내에서 navigate 쓸수 없을때( To solve createAsyncThunk asynchronous function can't navigate)

해당 이슈는 redux-toolkit 비동기 함수 호출시 사용시 사용되는 createAsyncThunk에서 발생된 이슈이다.

필자는 비동기 함수가 실행된 후 response값이 true로 들어올때 다른 페이지로 이동을 위해 useNavigate을 해당 함수에 호출하여 사용하였으나 작동하지 않았다. 

이유는 정확하게 알수 없었지만, 다양한 해결방안들을 둘러보면서 몇가지 대안들을 찾았다.

하단 코드는 우선 navigate 가 실행되지 않는 slice 구문이다.

This issue is made from the createAsyncThunk when you are trying to use the asynchrounus function inside it.

Especially navigate can't work almost situation. I don't know the reason why i look around various solutions and find some nice answers.

Anyway the below code is the error point.

import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import api from "../../common/api";
import { useNavigate } from "react-router-dom";
export const goLogin = createAsyncThunk("login", async (param) => {
  const res = await api.post("user/login", param);
  return res.data;
});

export const addUser = createAsyncThunk("addUser", async (param) => {
  const res = await api.post("user/addUser", param);
  if (res.data.ok) {
    const navigate = useNavigate();
    navigate("/"); //***내부에서 작동되지 않음
  }
  return res.data;
});
const initialState = {
  section: "로그인",
  i: 0,
  status: null,
  isLoggedIn: false,
  addok: false,
  userId: "",
};

const loginSlice = createSlice({
  name: "섹션",
  initialState,
  reducers: {
    onLoggedIn: (state, action) => {
      state.isLoggedIn = action.payload;
    },
  },

  extraReducers: {
    [goLogin.fulfilled]: (state, action) => {
      state.status = "success";
      state.isLoggedIn = action.payload;
    },
    [addUser.fulfilled]: (state, action) => {
      state.status = "success";
      state.addok = action.payload;
      state.userId = action.payload.userId;
    },
  },
});

export const { onLoggedIn } = loginSlice.actions;

export default loginSlice.reducer;

여러가지 찾아보았지만 가장 효울적인 방법은 useDispatch안의 내장함수.unwrap을 사용하는 것이다.

참고할만한 코드를 아래에 제시해놓았다.

기존 slice내부에서 가지고왔던 resonse값을 dispatch 직접실행시 불러와 하단과 같이 간단히 실행이 가능하다.

The effective way that solve this problem is using the built-in-function named unwrap. It is the easiest way to puzzled out. You can use with the dispatch , the example code is on the below.

  const Loginin = async () => {
    try {
      const response = await dispatch(adminLogin(loginInput)).unwrap();
      console.log(response);
      if (response.ok === true) {
        navigate("/admin");
        window.localStorage.setItem("adminUserId", loginInput.adminId);
      } else {
        alert("잘못된 아이디 비번");
      }
    } catch (error) {
      console.log(error);
    }
  };