来自一个切片的动作正在使用Redux Toolkit更改另一个切片的状态

von4xj4u  于 2023-11-19  发布在  其他
关注(0)|答案(1)|浏览(136)

我用的是redux toolkit。
我有不同的切片,它们有自己的状态。
我有一个切片角色

  1. import { createSlice } from '@reduxjs/toolkit';
  2. import { getAllRoles } from './roleActions';
  3. const initialState = {
  4. roles: [],
  5. loading: false,
  6. isSuccess: false,
  7. message: '',
  8. };
  9. const authReducer = createSlice({
  10. name: 'roles',
  11. initialState,
  12. reducers: {},
  13. extraReducers: (builder) => {
  14. builder
  15. .addCase(getAllRoles.pending, (state) => {
  16. state.isSuccess = false;
  17. state.message = '';
  18. state.loading = true;
  19. })
  20. .addCase(getAllRoles.fulfilled, (state, { payload }) => {
  21. state.roles = payload.data;
  22. state.message = payload.message;
  23. state.isSuccess = true;
  24. state.loading = false;
  25. })
  26. .addCase(getAllRoles.rejected, (state, { payload }) => {
  27. state.isSuccess = false;
  28. state.message = payload;
  29. state.loading = false;
  30. });
  31. },
  32. });
  33. export default authReducer.reducer;

字符串
下面是getAllRoles操作

  1. import { createAsyncThunk } from '@reduxjs/toolkit';
  2. import API from '../../api';
  3. import { formatError } from '@utils/index';
  4. export const getAllRoles = createAsyncThunk('role/getAllRoles', async (_, { rejectWithValue }) => {
  5. try {
  6. const { data } = await API.get('/roles');
  7. return data;
  8. } catch (error) {
  9. return rejectWithValue(formatError(error));
  10. }
  11. });


我正在获取所有角色:

  1. useEffect(() => {
  2. dispatch(getAllRoles());
  3. }, [dispatch]);


另一片:

  1. import { createSlice } from '@reduxjs/toolkit';
  2. import { deleteJob, getJobs, updateJob, createJob } from './jobActions';
  3. const initialValues = {
  4. data: {
  5. jobs: [],
  6. totalCount: 0,
  7. },
  8. loading: false,
  9. isSuccess: false,
  10. message: '',
  11. };
  12. const jobsReducer = createSlice({
  13. name: 'jobs',
  14. initialState: initialValues,
  15. reducers: {},
  16. extraReducers: (builder) => {
  17. // Get Jobs
  18. builder
  19. .addCase(getJobs.fulfilled, (state, { payload }) => {
  20. return {
  21. ...state,
  22. data: payload.data,
  23. message: payload.message,
  24. isSuccess: true,
  25. loading: false,
  26. };
  27. })
  28. .addCase(deleteJob.fulfilled, (state, { payload }) => {
  29. const updatedJobs = [...state.data.jobs.filter((job) => job._id !== payload)];
  30. return {
  31. ...state,
  32. data: {
  33. totalCount: state.data.totalCount - 1,
  34. jobs: updatedJobs,
  35. },
  36. message: 'Job deleted successfully',
  37. isSuccess: true,
  38. loading: false,
  39. };
  40. })
  41. .addCase(updateJob.fulfilled, (state, { payload }) => {
  42. const updatedJobs = [...state.data.jobs.filter((job) => job._id !== payload.data._id), payload.data];
  43. return {
  44. ...state,
  45. data: {
  46. totalCount: state.data.totalCount,
  47. jobs: updatedJobs,
  48. },
  49. message: payload.message,
  50. isSuccess: true,
  51. loading: false,
  52. };
  53. })
  54. .addCase(createJob.fulfilled, (state, { payload }) => {
  55. return {
  56. ...state,
  57. data: {
  58. totalCount: state.data.totalCount + 1,
  59. jobs: [payload.data, ...state.data.jobs],
  60. },
  61. message: payload.message,
  62. isSuccess: true,
  63. loading: false,
  64. };
  65. })
  66. .addMatcher(
  67. (action) => action.type.endsWith('/pending'),
  68. (state) => ({
  69. ...state,
  70. isSuccess: false,
  71. message: '',
  72. loading: true,
  73. }),
  74. )
  75. .addMatcher(
  76. (action) => action.type.endsWith('/rejected'),
  77. (state, { payload }) => ({
  78. ...state,
  79. isSuccess: false,
  80. message: payload,
  81. loading: false,
  82. }),
  83. );
  84. },
  85. });
  86. export default jobsReducer.reducer;


再来一个slice:

  1. import { createUser, deleteUser, getUsers, updateUser } from './userActions';
  2. const initialState = {
  3. users: [],
  4. loading: false,
  5. isSuccess: false,
  6. message: '',
  7. };
  8. const usersReducer = createSlice({
  9. name: 'users',
  10. initialState,
  11. reducers: {},
  12. extraReducers: (builder) => {
  13. // Get Users
  14. builder.addCase(getUsers.fulfilled, (state, { payload }) => {
  15. state.loading = false;
  16. state.message = payload.message;
  17. state.users = payload.data;
  18. state.isSuccess = true;
  19. });
  20. // Delete Users
  21. builder.addCase(deleteUser.fulfilled, (state, { payload }) => {
  22. state.loading = false;
  23. state.message = payload.message;
  24. state.users = [...state.users.filter((user) => user._id !== payload)];
  25. state.isSuccess = true;
  26. });
  27. // Update User
  28. builder.addCase(updateUser.fulfilled, (state, { payload }) => {
  29. state.loading = false;
  30. state.message = payload.message;
  31. state.users.splice(
  32. state.users.findIndex((user) => user.email === payload.data.email),
  33. 1,
  34. payload.data,
  35. );
  36. state.isSuccess = true;
  37. state.message = payload.message;
  38. });
  39. // Create User
  40. builder.addCase(createUser.fulfilled, (state, { payload }) => {
  41. state.loading = false;
  42. state.message = payload.message;
  43. state.users.unshift(payload.data);
  44. state.isSuccess = true;
  45. });
  46. // Pending State
  47. builder.addMatcher(
  48. (action) => action.type.endsWith('/pending'),
  49. (state) => {
  50. state.isSuccess = false;
  51. state.message = '';
  52. state.loading = true;
  53. },
  54. );
  55. // Rejected State
  56. builder.addMatcher(
  57. (action) => action.type.endsWith('/rejected'),
  58. (state, { payload }) => {
  59. state.isSuccess = false;
  60. state.message = payload;
  61. state.loading = false;
  62. },
  63. );
  64. },
  65. });
  66. export default usersReducer.reducer;


现在的问题是,当getAllRoles触发时,它应该将其加载状态更改为true,这样它就正确了,
但它也会将用户和作业的加载状态更改为true,仅将加载状态更改为true,而不会重新设置为false。
就像我有一些其他的切片一样,它们也是这样的,
当我调度getJobs的操作时,
现在它也有不同的行为,比如它将用户的加载状态更改为true,而不是角色或任何其他角色。
以下是redux devtools的截图:
x1c 0d1x的数据
我已经选择了roles/getAllRoles/pending action,并检查了状态差异,它正在改变其他切片的加载状态,这是不应该的。
以下是我的商店配置:

  1. import storage from 'redux-persist/lib/storage';
  2. import { combineReducers } from 'redux';
  3. import { persistReducer } from 'redux-persist';
  4. import thunk from 'redux-thunk';
  5. import { authReducer, usersReducer, rolesReducer, jobsReducer, surveysReducer, pageInfoReducer } from './features';
  6. const reducers = combineReducers({
  7. auth: authReducer,
  8. users: usersReducer,
  9. roles: rolesReducer,
  10. jobs: jobsReducer,
  11. survey: surveysReducer,
  12. pageInfo: pageInfoReducer,
  13. });
  14. const store = configureStore({
  15. reducer: reducers,
  16. devTools: process.env.NODE_ENV !== 'production',
  17. middleware: [thunk],
  18. });
  19. export default store;


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

mbskvtky

mbskvtky1#

问题

作业和用户状态切片都定义了reducer cases,用于处理 * 任何**挂起或拒绝的操作。

  1. const jobsReducer = createSlice({
  2. name: 'jobs',
  3. initialState: initialValues,
  4. reducers: {},
  5. extraReducers: (builder) => {
  6. // Get Jobs
  7. builder
  8. ...
  9. .addMatcher(
  10. (action) => action.type.endsWith('/pending'), // <-- any pending
  11. (state) => ({
  12. ...state,
  13. isSuccess: false,
  14. message: '',
  15. loading: true,
  16. }),
  17. )
  18. .addMatcher(
  19. (action) => action.type.endsWith('/rejected'), // <-- any rejected
  20. (state, { payload }) => ({
  21. ...state,
  22. isSuccess: false,
  23. message: payload,
  24. loading: false,
  25. }),
  26. );
  27. },
  28. });

个字符
'role/getAllRoles/pending'被分派到store时,这些其他reducer case将使用当前代码正确更新并设置其本地loading状态(* 以及它们case中的状态更新 *)。如果异步getAllRoles操作成功完成,则这些其他状态切片中没有清除其加载状态的情况。

解决方案

回想一下,Redux store的reducer树中的所有reducer都会传递每个分派到store的action,并且只有具有特定action的case的reducer才会响应。
我怀疑您只对作业切片中deleteJobgetJobsupdateJobcreateJob操作的挂起/拒绝状态感兴趣,而对createUserdeleteUsergetUsers、对于用户切片,我建议使用isPendingisFulfilledisRejected匹配实用程序。
范例:

  1. import { createSlice, isPending, isFulfilled, isRejected } from '@reduxjs/toolkit';
  2. import { deleteJob, getJobs, updateJob, createJob } from './jobActions';
  3. const initialState = {
  4. data: {
  5. jobs: [],
  6. totalCount: 0,
  7. },
  8. loading: false,
  9. isSuccess: false,
  10. message: '',
  11. };
  12. const jobsReducer = createSlice({
  13. name: 'jobs',
  14. initialState,
  15. extraReducers: (builder) => {
  16. // Get Jobs
  17. builder
  18. .addCase(getJobs.fulfilled, (state, { payload }) => {
  19. return {
  20. ...state,
  21. data: payload.data,
  22. message: payload.message,
  23. };
  24. })
  25. .addCase(deleteJob.fulfilled, (state, { payload }) => {
  26. const updatedJobs = state.data.jobs.filter((job) => job._id !== payload);
  27. return {
  28. ...state,
  29. data: {
  30. totalCount: state.data.totalCount - 1,
  31. jobs: updatedJobs,
  32. },
  33. message: 'Job deleted successfully',
  34. };
  35. })
  36. .addCase(updateJob.fulfilled, (state, { payload }) => {
  37. return {
  38. ...state,
  39. data: {
  40. totalCount: state.data.totalCount,
  41. jobs: state.data.jobs
  42. .filter((job) => job._id !== payload.data._id)
  43. .concat(payload.data),
  44. },
  45. message: payload.message,
  46. };
  47. })
  48. .addCase(createJob.fulfilled, (state, { payload }) => {
  49. return {
  50. ...state,
  51. data: {
  52. totalCount: state.data.totalCount + 1,
  53. jobs: [payload.data, ...state.data.jobs],
  54. },
  55. message: payload.message,
  56. };
  57. })
  58. .addMatcher(
  59. isPending(deleteJob, getJobs, updateJob, createJob),
  60. (state) => {
  61. state.isSuccess: false,
  62. state.message: '',
  63. state.loading: true,
  64. },
  65. )
  66. .addMatcher(
  67. isFulfilled(deleteJob, getJobs, updateJob, createJob),
  68. (state) => {
  69. state.isSuccess: true,
  70. state.loading: false,
  71. },
  72. )
  73. .addMatcher(
  74. isRejected(deleteJob, getJobs, updateJob, createJob),
  75. (state, { payload }) => {
  76. state.isSuccess: false,
  77. state.message: payload,
  78. state.loading: false,
  79. },
  80. );
  81. },
  82. });
  1. import { createSlice, isPending, isFulfilled, isRejected } from '@reduxjs/toolkit';
  2. import { createUser, deleteUser, getUsers, updateUser } from './userActions';
  3. const initialState = {
  4. users: [],
  5. loading: false,
  6. isSuccess: false,
  7. message: '',
  8. };
  9. const usersReducer = createSlice({
  10. name: 'users',
  11. initialState,
  12. extraReducers: (builder) => {
  13. // Get Users
  14. builder.addCase(getUsers.fulfilled, (state, { payload }) => {
  15. state.message = payload.message;
  16. state.users = payload.data;
  17. });
  18. // Delete Users
  19. builder.addCase(deleteUser.fulfilled, (state, { payload }) => {
  20. state.message = payload.message;
  21. state.users = [...state.users.filter((user) => user._id !== payload)];
  22. });
  23. // Update User
  24. builder.addCase(updateUser.fulfilled, (state, { payload }) => {
  25. state.message = payload.message;
  26. state.users.splice(
  27. state.users.findIndex((user) => user.email === payload.data.email),
  28. 1,
  29. payload.data,
  30. );
  31. });
  32. // Create User
  33. builder.addCase(createUser.fulfilled, (state, { payload }) => {
  34. state.message = payload.message;
  35. state.users.unshift(payload.data);
  36. });
  37. // Pending State
  38. builder.addMatcher(
  39. isPending(createUser, deleteUser, getUsers, updateUser),
  40. (state) => {
  41. state.isSuccess = false;
  42. state.message = '';
  43. state.loading = true;
  44. },
  45. );
  46. // Fulfilled State
  47. builder.addMatcher(
  48. isFulfilled(createUser, deleteUser, getUsers, updateUser),
  49. (state) => {
  50. state.isSuccess = true;
  51. state.message = '';
  52. state.loading = false;
  53. },
  54. );
  55. // Rejected State
  56. builder.addMatcher(
  57. isRejected(createUser, deleteUser, getUsers, updateUser),
  58. (state, { payload }) => {
  59. state.isSuccess = false;
  60. state.message = payload;
  61. state.loading = false;
  62. },
  63. );
  64. },
  65. });

的字符串

展开查看全部

相关问题