Search code examples
reactjsreduxredux-toolkitredux-thunk

unexpected behaviour of dispatching action in redux


I have the following async thunk function:

const loadProject = createAsyncThunk(
  '[Project API] Load Project',
  async (project: IKProject, { dispatch }) => {
    await kProjectService.loadProject(project)

    localStorage.setItem(STORAGE_KEY, project)
    dispatch(projectActions.setLoadedProject(project))

    // Loading & saving the project configuration
    const config = await kProjectService.getProjectConfig(project)
    dispatch(projectActions.setProjectConfig(config))
  }
)

const unLoadProject = createAsyncThunk(
  '[Project API] Un Load Project',
  async (project: IKProject, { dispatch }) => {
    await kProjectService.closeProject(project)
    dispatch(projectActions.resetState())
  }
)

const refreshProject = createAsyncThunk(
  '[Project API] Refresh Project',
  async (project: IKProject, { dispatch }) => {
    await dispatch(projectActions.unLoadProject(project))
    await dispatch(projectActions.loadProject(project))

    console.log('After refreshing')
  }
)

Project service:

import { IKProject, IKProjectConfig } from '@/Types'
import { httpService } from './http.service'

function loadProject(project: IKProject): Promise<IKProject> {
  return httpService.post(`/project/load`, project)
}

function loadProjectConfig(project: IKProject): Promise<IKProjectConfig> {
  return httpService.get(`/project/config`, project)
}

function closeProject(project: IKProject): Promise<unknown> {
  return httpService.delete(`/project/${project.name}/close`, project)
}

export const kProjectService = {
  loadProject,
  loadProjectConfig,
  closeProject,
}

Project slice looks like that

const projectSlice = createSlice({
  name: '[Project API]',
  initialState,
  reducers: {
    resetState: () => initialState,
    setLoadedProject: (state, action: PayloadAction<IKProject | null>) => {
      state.kLoadedProject = action.payload
    },
    setProjectConfig: (
      state,
      action: PayloadAction<IKProjectConfig | null>
    ) => {
      state.kConfig = action.payload
    },
    reducers...
  },
  extraReducers(builder) {
    builder
      .addCase(projectActions.refreshProject.pending, (state) => {
        state.isRefreshing = true
      })
      .addMatcher(
        isAnyOf(
          projectActions.refreshProject.rejected,
          projectActions.refreshProject.fulfilled
        ),
        (state) => {
          state.isRefreshing = false
        }
      )
  },
  selectors: {
    selectors...
  }
})

the isRefreshing in the initialState sets to false by default.
According to the defined extraReducers it's automatically changing based on the status of the promise (thunk function), now the issue that I'm facing is that when the refreshProject action executed it resolved immediately instead of waiting for the other's actions to finish.

after debugging, I do see the isRefreshing changing from false -> true -> false

NOTE: I do see the output of console.log('After refreshing') after the loadProject action is finished and this is why I don't get why the thunk is resolved immediately.

Please help.


Solution

  • looks like the resetState() action in unLoadProject caused the problem here.

    resolved: https://github.com/reduxjs/redux-toolkit/issues/4528