Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

action.payload in creactAsyncThunk is undefined

I am trying to get user data from api using axios with createAsyncThunk, and want the user data to be stored in state by the fulfilled action dispatched by the createAsyncThunk.

As mentioned in the docs

if the promise resolved successfully, dispatch the fulfilled action with the promise value as action.payload.

But the action.payload in undefined in the fulfilled action creator.

Here is my code.

/// Create Async Thunk
export const fetchUserData = createAsyncThunk(
  'user/fetchUserData',
  (payload, { dispatch }) => {
    axios
      .get('/user')
      .then(res => {
        console.log(res.data);
        //Used this as a work around for storing data
        dispatch(setUser(res.data));

        return res.data;
       })
      .catch(err => {
        console.error(err);
        return err;
      });
  }
);

/// On Fulfilled
const userSlice = createSlice({
...
  extraReducers:{
  ...
  [fetchUserData.fulfilled]: (state, action) => {
        // Payload is undefined
        state.data = action.payload
      },
  }
}
like image 972
skyraider Avatar asked Jul 28 '20 07:07

skyraider


2 Answers

createAsyncThunk accepts two parameters:

  1. type
  2. payloadCreator

Where payloadCreator is a callback function that should return a promise (containing the result of some asynchronous logic) or a value (synchronously).

So, you can either write:

export const fetchUserData = createAsyncThunk(
  'user/fetchUserData',
  (payload, { dispatch }) => {
    return axios.get('/user'); // Return a promise
  }
);

or

export const fetchUserData = createAsyncThunk(
  'user/fetchUserData',
  async (payload, { dispatch, rejectWithValue }) => {
    try {
      const response = await axios.get('/user')
      return response // Return a value synchronously using Async-await
    } catch (err) {
      if (!err.response) {
        throw err
      }
      return rejectWithValue(err.response)
    }
  }
);
like image 117
Ajeet Shah Avatar answered Sep 27 '22 17:09

Ajeet Shah


An addition to @Ajeet Shah's answer:

According to the documentation a rejected promise must return either

  • an Error-instance, as in new Error(<your message>),
  • a plain value, such as a descriptive String,
  • or a RejectWithValue return by thunkAPI.rejectWithValue()

With the first two options, and I haven't tested the last option, the payload will also by undefined, but an error parameter will be given containing your rejected message.

See this example:

const loginAction = createAsyncThunk(
  "user/login",
  (payload, { getState }) => {
    const { logged_in, currentRequestId, lastRequestId } = getState().login;

    // Do not login if user is already logged in
    if (logged_in) {
      return Promise.reject(new Error(Cause.LoggedIn));
    }

    // Do not login if there is a pending login request
    else if (lastRequestId != null && lastRequestId !== currentRequestId) {
      return Promise.reject(new Error(Cause.Concurrent));
    }

    // May as well try logging in now...
    return AccountManager.login(payload.email, payload.password);
  }
);
like image 39
Sebastian Avatar answered Sep 27 '22 18:09

Sebastian