ajhavery
ajhavery

Reputation: 424

Redux Toolkit: createAsyncThunk - rejectWithValue - TypeError: Cannot destructure property 'rejectWithValue' of '_ref2' as it is undefined."

I've been trying to make auth refresh token calls using Redux toolkit but after installing all fixes, it still is now able to read error message.

Setting up axios instance:

export const axiosInstance = axios.create({
  baseURL: REACT_APP_API_URL,
});

Making API call:

export const refreshAccessAndRefreshTokens = async () => {
  const response = await axiosInstance({
    method: 'post',
    url: '/refresh-tokens',
    withCredentials: true,
  });
  return response;
};

Thunk function:

// GET ACCESS TOKEN USING REFRESH TOKEN
export const refreshTokens = createAsyncThunk(
  'auth/refreshTokens',
  async ({ rejectWithValue }) => {
    try {
      const response = await refreshAccessAndRefreshTokens();
      return response.data;
    } catch (error) {
      console.log('error', error);
      console.log('data', error.response.data);
      console.log('message', error.response.data.message);
      return rejectWithValue(error.response.data.message);
    }
  }
);

Extra reducers in auth slice:

extraReducers: (builder) => {
    builder
      .addCase(refreshTokens.pending, (state) => {
        state.loading = true;
      })
      .addCase(refreshTokens.fulfilled, (state, action) => {
        state.loading = false;
        state.isAuthenticated = true;
        state.user = action.payload.user;
        state.roles = action.payload.roles;
      })
      .addCase(refreshTokens.rejected, (state, action) => {
        state.loading = false;
        state.success = false;
        state.message = action.payload;
        state.isAuthenticated = false;
        state.user = null;
        state.roles = [];
      })
  },

I'm able to see the errors in browser console, but rejectWithMessage is not working:

Console output:

console output

Redux output:

redux output

Refresh Tokens is being called on login page through useEffect to redirect the user to where he came from in case he is already logged in.

useEffect(() => {
    dispatch(refreshTokens());
    dispatch(reset());
  }, [dispatch]);

  useEffect(() => {
    if (isAuthenticated) {
      if (roles.find((role) => role === process.env.REACT_APP_ROLE)) {
        navigate(from, { replace: true });
      } else {
        dispatch(
          errorFn({
            success: false,
            message: 'You are not authorized to access this page!',
          })
        );
      }
    }
  }, [dispatch, from, isAuthenticated, navigate, roles]);

Upvotes: 1

Views: 4157

Answers (2)

HasanRadi93
HasanRadi93

Reputation: 27

export const canLogin = createAsyncThunk("AUTH/login", 
async (loginData ,{ rejectWithValue })=> {
    try{
        const response=await axios.post(AuthConfig.API_URL + AuthConfig.LOGIN_URI, loginData)
        return response
    }
    catch(error){
        if (!error.response || !error.message) 
            throw error
        return rejectWithValue(getErrorMessage(error))
    }    
  }
);

export function getErrorMessage(error) {
    return (
      error?.response?.data?.message ||
      error?.response?.data.error ||
      error?.response?.data ||
      error?.message ||
      error.toString()
    );
}

Upvotes: -1

jon doe
jon doe

Reputation: 544

The first argument that is passed to the callback function you give to createAsyncThunk is the argument that you pass when you call the action. take a look here for more information. The second argument is the thunkAPI which contains the rejectWithValue. Try putting a dummy parameter as the first parameter to the callback like this -

// GET ACCESS TOKEN USING REFRESH TOKEN
export const refreshTokens = createAsyncThunk(
  'auth/refreshTokens',
  async (_, { rejectWithValue }) => {
    try {
      const response = await refreshAccessAndRefreshTokens();
      return response.data;
    } catch (error) {
      console.log('error', error);
      console.log('data', error.response.data);
      console.log('message', error.response.data.message);
      return rejectWithValue(error.response.data.message);
    }
  }
);

Upvotes: 5

Related Questions