Search code examples
reactjstypescriptredux-toolkitrtk-query

Use Redux-Toolkit mutation with createAsyncThunk


I want to create a login API call from the auth slice. I use both Redux-Toolkit (RTK) and RTK Query in the project. I want to use fetchBaseQuery in the API call. I have predefined baseQuery.

export const baseQuery = retry(fetchBaseQuery({
  timeout: 5000,
  headers: {
    'Content-Type': 'application/json;charset=utf-8',
    'Access-Control-Allow-Origin': '*',
  },
  prepareHeaders: (headers, { getState }) => {
    const accessToken = localStorage.getItem(AUTH_TOKEN_KEY) || '';
    const uid = getLocal(UID_KEY);
    if (accessToken) {
      headers.set('Authorization', accessToken);
      headers.set(UID_KEY, uid);
    }
    return headers;
  },
}), { maxRetries: 3 });

My expectation is to use a RTK mutation in the authSlice. I have tried like this, but it is not working.

export const loginAsync = createAsyncThunk(
  'auth/login',
  async (credentials: LoginValuesType, thunkAPI) => {
    try {
      // How to call the mutation here?
      // const response = await userApi.useLoginMutation(credentials)
    
      if (response?.data?.code === 0) {
        localStorage.setItem(AUTH_TOKEN_KEY, response.data?.data?.token);
        setLocal('uid', response.data?.data?.uid);
        return response.data;
      } else if (response?.data?.code === 1) {
        thunkAPI.dispatch(showError(response?.data?.msg))
        return thunkAPI.rejectWithValue({msg: response?.data?.msg})
      }
    } catch (e) {
      thunkAPI.dispatch(showError('An error occurred'))
      return thunkAPI.rejectWithValue({msg: "An error occurred"})
    }
  }
)

If this way is impossible please suggest me a good way to create this backend connection.

This is the RTK mutation I have implemented. We can remove it if it is not necessary.

export const userApi = createApi({
  reducerPath: 'userApi',
  baseQuery: baseQuery,
  endpoints: (builder) => ({       
    login: builder.mutation({
      query: (args) => {
        return {
          url: '/api/v1/sign_in',
          method: 'POST',
          body: args,
        }
      },
    }),
  }),
});

export const {
  useLoginMutation
} = userApi;

Solution

  • You can initiate an endpoint directly. Example:

    export const loginAsync = createAsyncThunk(
      'auth/login',
      async (credentials: LoginValuesType, thunkApi) => {
        try {
          const { data } = await thunkApi.dispatch(
            userApi.endpoints.login.initiate(credentials);
          );
        
          if (data.code === 0) {
            localStorage.setItem(AUTH_TOKEN_KEY, data.data?.token);
            setLocal('uid', data.data?.uid);
            return data;
          } else if (data.code === 1) {
            const { msg } = data;
            thunkApi.dispatch(showError(msg));
            return thunkApi.rejectWithValue({ msg });
          }
        } catch (e) {
          thunkApi.dispatch(showError('An error occurred'));
          return thunkApi.rejectWithValue({ msg: "An error occurred" });
        }
      }
    );