一个切片的操作正在使用 redux 工具包更改另一个切片的状态

问题描述 投票:0回答:1

我正在使用 redux 工具包。

我有不同的切片,它们有自己的状态。

我有一个角色

import { createSlice } from '@reduxjs/toolkit';
import { getAllRoles } from './roleActions';

const initialState = {
  roles: [],
  loading: false,
  isSuccess: false,
  message: '',
};

const authReducer = createSlice({
  name: 'roles',
  initialState,

  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(getAllRoles.pending, (state) => {
        state.isSuccess = false;
        state.message = '';
        state.loading = true;
      })
      .addCase(getAllRoles.fulfilled, (state, { payload }) => {
        state.roles = payload.data;
        state.message = payload.message;
        state.isSuccess = true;
        state.loading = false;
      })
      .addCase(getAllRoles.rejected, (state, { payload }) => {
        state.isSuccess = false;
        state.message = payload;
        state.loading = false;
      });
  },
});

export default authReducer.reducer;

这是 getAllRoles 操作

import { createAsyncThunk } from '@reduxjs/toolkit';
import API from '../../api';
import { formatError } from '@utils/index';

export const getAllRoles = createAsyncThunk('role/getAllRoles', async (_, { rejectWithValue }) => {
  try {
    const { data } = await API.get('/roles');
    return data;
  } catch (error) {
    return rejectWithValue(formatError(error));
  }
});

我将所有角色获取为:

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

另一片:

import { createSlice } from '@reduxjs/toolkit';
import { deleteJob, getJobs, updateJob, createJob } from './jobActions';

const initialValues = {
  data: {
    jobs: [],
    totalCount: 0,
  },
  loading: false,
  isSuccess: false,
  message: '',
};

const jobsReducer = createSlice({
  name: 'jobs',
  initialState: initialValues,
  reducers: {},
  extraReducers: (builder) => {
    // Get Jobs
    builder
      .addCase(getJobs.fulfilled, (state, { payload }) => {
        return {
          ...state,
          data: payload.data,
          message: payload.message,
          isSuccess: true,
          loading: false,
        };
      })
      .addCase(deleteJob.fulfilled, (state, { payload }) => {
        const updatedJobs = [...state.data.jobs.filter((job) => job._id !== payload)];
        return {
          ...state,
          data: {
            totalCount: state.data.totalCount - 1,
            jobs: updatedJobs,
          },
          message: 'Job deleted successfully',
          isSuccess: true,
          loading: false,
        };
      })
      .addCase(updateJob.fulfilled, (state, { payload }) => {
        const updatedJobs = [...state.data.jobs.filter((job) => job._id !== payload.data._id), payload.data];
        return {
          ...state,
          data: {
            totalCount: state.data.totalCount,
            jobs: updatedJobs,
          },
          message: payload.message,
          isSuccess: true,
          loading: false,
        };
      })
      .addCase(createJob.fulfilled, (state, { payload }) => {
        return {
          ...state,
          data: {
            totalCount: state.data.totalCount + 1,
            jobs: [payload.data, ...state.data.jobs],
          },
          message: payload.message,
          isSuccess: true,
          loading: false,
        };
      })
      .addMatcher(
        (action) => action.type.endsWith('/pending'),
        (state) => ({
          ...state,
          isSuccess: false,
          message: '',
          loading: true,
        }),
      )
      .addMatcher(
        (action) => action.type.endsWith('/rejected'),
        (state, { payload }) => ({
          ...state,
          isSuccess: false,
          message: payload,
          loading: false,
        }),
      );
  },
});

export default jobsReducer.reducer;

再来一片:

import { createUser, deleteUser, getUsers, updateUser } from './userActions';

const initialState = {
  users: [],
  loading: false,
  isSuccess: false,
  message: '',
};

const usersReducer = createSlice({
  name: 'users',
  initialState,
  reducers: {},
  extraReducers: (builder) => {
    // Get Users
    builder.addCase(getUsers.fulfilled, (state, { payload }) => {
      state.loading = false;
      state.message = payload.message;
      state.users = payload.data;
      state.isSuccess = true;
    });

    // Delete Users
    builder.addCase(deleteUser.fulfilled, (state, { payload }) => {
      state.loading = false;
      state.message = payload.message;
      state.users = [...state.users.filter((user) => user._id !== payload)];
      state.isSuccess = true;
    });

    // Update User
    builder.addCase(updateUser.fulfilled, (state, { payload }) => {
      state.loading = false;
      state.message = payload.message;
      state.users.splice(
        state.users.findIndex((user) => user.email === payload.data.email),
        1,
        payload.data,
      );
      state.isSuccess = true;
      state.message = payload.message;
    });

    // Create User
    builder.addCase(createUser.fulfilled, (state, { payload }) => {
      state.loading = false;
      state.message = payload.message;
      state.users.unshift(payload.data);
      state.isSuccess = true;
    });

    // Pending State
    builder.addMatcher(
      (action) => action.type.endsWith('/pending'),
      (state) => {
        state.isSuccess = false;
        state.message = '';
        state.loading = true;
      },
    );

    // Rejected State
    builder.addMatcher(
      (action) => action.type.endsWith('/rejected'),
      (state, { payload }) => {
        state.isSuccess = false;
        state.message = payload;
        state.loading = false;
      },
    );
  },
});

export default usersReducer.reducer;

现在的问题是,当 getAllRoles 触发时,它应该将其加载状态更改为 true 以确保其正确执行,

但它也会将用户和作业的加载状态更改为 true,仅更改加载状态,并且不会设置回 false。

就像我有其他一些切片一样,它们也有这样的行为,

当我调度 getJobs 的操作时

现在它还有不同的行为,例如它将用户的加载状态更改为 true,但不更改角色或任何其他的加载状态。

这是 redux devtools 截图:

我选择了 Roles/getAllRoles/pending 操作,并检查状态差异,它正在更改其他切片的加载状态,但它也不应该这样做。

这是我的商店配置:

import storage from 'redux-persist/lib/storage';
import { combineReducers } from 'redux';
import { persistReducer } from 'redux-persist';
import thunk from 'redux-thunk';
import { authReducer, usersReducer, rolesReducer, jobsReducer, surveysReducer, pageInfoReducer } from './features';

const reducers = combineReducers({
  auth: authReducer,
  users: usersReducer,
  roles: rolesReducer,
  jobs: jobsReducer,
  survey: surveysReducer,
  pageInfo: pageInfoReducer,
});

const store = configureStore({
  reducer: reducers,
  devTools: process.env.NODE_ENV !== 'production',
  middleware: [thunk],
});

export default store;

尝试删除addMatcher,使用动作和切片的唯一名称,尝试单独使用builder.addCase而不是改变方式。没有任何效果。

javascript reactjs redux redux-toolkit redux-thunk
1个回答
0
投票

问题

作业和用户状态切片都定义了处理任何待处理或拒绝的操作的减速器案例。

const jobsReducer = createSlice({
  name: 'jobs',
  initialState: initialValues,
  reducers: {},
  extraReducers: (builder) => {
    // Get Jobs
    builder
      ...
      .addMatcher(
        (action) => action.type.endsWith('/pending'), // <-- any pending
        (state) => ({
          ...state,
          isSuccess: false,
          message: '',
          loading: true,
        }),
      )
      .addMatcher(
        (action) => action.type.endsWith('/rejected'), // <-- any rejected
        (state, { payload }) => ({
          ...state,
          isSuccess: false,
          message: payload,
          loading: false,
        }),
      );
  },
});
const usersReducer = createSlice({
  name: 'users',
  initialState,
  reducers: {},
  extraReducers: (builder) => {
    ...

    // Pending State
    builder.addMatcher(
      (action) => action.type.endsWith('/pending'), // <-- any pending
      (state) => {
        state.isSuccess = false;
        state.message = '';
        state.loading = true;
      },
    );

    // Rejected State
    builder.addMatcher(
      (action) => action.type.endsWith('/rejected'), // <-- any rejected
      (state, { payload }) => {
        state.isSuccess = false;
        state.message = payload;
        state.loading = false;
      },
    );
  },
});

'role/getAllRoles/pending'
被分派到存储时,这些其他减速器案例将使用当前代码正确更新和设置其本地
loading
状态(以及其案例中的状态更新)。如果异步
getAllRoles
操作成功完成,则在这些其他状态片中不存在清除其加载状态的情况。

解决方案

回想一下,Redux 存储的减速器树中的所有减速器都会传递分派到存储的每个操作,并且只有具有特定操作案例的减速器才会响应。

我怀疑您对作业切片情况下

deleteJob
getJobs
updateJob
createJob
操作的待处理/拒绝状态感兴趣,并且在用户切片的情况下,
createUser
deleteUser
getUsers
updateUser
的待处理/拒绝状态。为此,我建议使用
isPending
isFulfilled
isRejected
匹配实用程序。

示例:

import { createSlice, isPending, isFulfilled, isRejected } from '@reduxjs/toolkit';
import { deleteJob, getJobs, updateJob, createJob } from './jobActions';

const initialState = {
  data: {
    jobs: [],
    totalCount: 0,
  },
  loading: false,
  isSuccess: false,
  message: '',
};

const jobsReducer = createSlice({
  name: 'jobs',
  initialState,
  extraReducers: (builder) => {
    // Get Jobs
    builder
      .addCase(getJobs.fulfilled, (state, { payload }) => {
        return {
          ...state,
          data: payload.data,
          message: payload.message,
        };
      })
      .addCase(deleteJob.fulfilled, (state, { payload }) => {
        const updatedJobs = state.data.jobs.filter((job) => job._id !== payload);
        return {
          ...state,
          data: {
            totalCount: state.data.totalCount - 1,
            jobs: updatedJobs,
          },
          message: 'Job deleted successfully',
        };
      })
      .addCase(updateJob.fulfilled, (state, { payload }) => {
        return {
          ...state,
          data: {
            totalCount: state.data.totalCount,
            jobs: state.data.jobs
              .filter((job) => job._id !== payload.data._id)
              .concat(payload.data),
          },
          message: payload.message,
        };
      })
      .addCase(createJob.fulfilled, (state, { payload }) => {
        return {
          ...state,
          data: {
            totalCount: state.data.totalCount + 1,
            jobs: [payload.data, ...state.data.jobs],
          },
          message: payload.message,
        };
      })
      .addMatcher(
        isPending(deleteJob, getJobs, updateJob, createJob),
        (state) => {
          state.isSuccess: false,
          state.message: '',
          state.loading: true,
        },
      )
      .addMatcher(
        isFulfilled(deleteJob, getJobs, updateJob, createJob),
        (state) => {
          state.isSuccess: true,
          state.loading: false,
        },
      )
      .addMatcher(
        isRejected(deleteJob, getJobs, updateJob, createJob),
        (state, { payload }) => {
          state.isSuccess: false,
          state.message: payload,
          state.loading: false,
        },
      );
  },
});
import { createSlice, isPending, isFulfilled, isRejected } from '@reduxjs/toolkit';
import { createUser, deleteUser, getUsers, updateUser } from './userActions';

const initialState = {
  users: [],
  loading: false,
  isSuccess: false,
  message: '',
};

const usersReducer = createSlice({
  name: 'users',
  initialState,
  extraReducers: (builder) => {
    // Get Users
    builder.addCase(getUsers.fulfilled, (state, { payload }) => {
      state.message = payload.message;
      state.users = payload.data;
    });

    // Delete Users
    builder.addCase(deleteUser.fulfilled, (state, { payload }) => {
      state.message = payload.message;
      state.users = [...state.users.filter((user) => user._id !== payload)];
    });

    // Update User
    builder.addCase(updateUser.fulfilled, (state, { payload }) => {
      state.message = payload.message;
      state.users.splice(
        state.users.findIndex((user) => user.email === payload.data.email),
        1,
        payload.data,
      );
    });

    // Create User
    builder.addCase(createUser.fulfilled, (state, { payload }) => {
      state.message = payload.message;
      state.users.unshift(payload.data);
    });

    // Pending State
    builder.addMatcher(
      isPending(createUser, deleteUser, getUsers, updateUser),
      (state) => {
        state.isSuccess = false;
        state.message = '';
        state.loading = true;
      },
    );

    // Fulfilled State
    builder.addMatcher(
      isFulfilled(createUser, deleteUser, getUsers, updateUser),
      (state) => {
        state.isSuccess = true;
        state.message = '';
        state.loading = false;
      },
    );

    // Rejected State
    builder.addMatcher(
      isRejected(createUser, deleteUser, getUsers, updateUser),
      (state, { payload }) => {
        state.isSuccess = false;
        state.message = payload;
        state.loading = false;
      },
    );
  },
});
© www.soinside.com 2019 - 2024. All rights reserved.