Alvaro Bataller
Alvaro Bataller

Reputation: 483

ReactJS and Redux Toolkit: Can I use 'createAsyncThunk()' to execute non-async side effects?

This is how my login action looks like and it works correctly:

export const login = createAsyncThunk(
'auth/login',
async (data, thunkAPI) => {
    const response = await API.login(data)

    //Store user data in local storage
    Storage.save('user', response.data)

    // Add token to HTTP headers
    API.setToken(response.data.key)

    return response.data
})

Now I need to do the logout function but when using "createSlice()" I have no option of adding side effects since it goes straight to the reducer (and Redux documentation says we should not add any side effects to the reducers)

// Slice
const authSlice = createSlice({
    name: 'auth',

    initialState: {
        user: null
    },

    reducers: {
        // Logout
        logout: (state, action) => {
            state.user = null
        },

    },
    extraReducers: {
        [login.fulfilled]: (state, action)=>{
            state.user = action.payload
        },
    }
})

So I thought I could maybe use the createAsyncThunk function to execute the side effects before it hits the reducer:

export const logout = createAsyncThunk(
    'auth/logout',
    async (thunkAPI) => {
        //Remove user data in local storage
        Storage.remove('user')

        // Remove token to HTTP headers
        API.removeToken()
    }
)

Is this an appropriate use of "createAsyncThunk"?

Hopefully someone with more experience can help with this.

Many thanks!

Upvotes: 6

Views: 3245

Answers (2)

Anarno
Anarno

Reputation: 1640

You have a second option. You can create a redux middleware, and you can do the custom logic there. In the middleware, you can filter the actions, and when the corresponding action comes then you can do side-effects. For example:

const customMiddleware = store => next => action => {
  console.log('dispatching', action)
  let result = next(action)
  console.log('next state', store.getState())
  if (action.type === 'EXPECTED_ACTION_TYPE') {
     // do the logic there
  }
  return result
}

Upvotes: 0

phry
phry

Reputation: 44078

It's a possible use, but an unnecessary one.

createAsyncThunk is an abstraction over normal "thunks actions" that dispaches a "pending" action before and a "fulfilled"/"rejected" action after. If you don't want these lifecycle actions, you can also just write a normal thunk. These are just so simple that RTK doesn't contain any helper for them.

const myThunkActionCreator = (id) => (dispatch, getState) => {
  // some sync or async stuff
  dispatch(someResult())
}

dispatch(myThunkActionCreator(5))

For more infos see this section of the official tutorials

Upvotes: 8

Related Questions