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

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

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

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;


再来一个slice:

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

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而不是改变方式。没有任何效果。

mbskvtky

mbskvtky1#

问题

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

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,
        }),
      );
  },
});

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

解决方案

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

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;
      },
    );
  },
});

的字符串

相关问题