调度动作或减速器?

Dispatching an action or a reducer?

我会注意到我理解 Redux 的标准数据流,你有一个动作创建者将类型通知给 reducer,reducer 将执行更新状态的魔法。

然而在 React-Redux (redux-toolkit) 中,当我发送一些东西时,它将直接成为一个 reducer,因此从概念上讲,当我想到它时,动作创建者丢失了,我正在努力理解 'reducer' 确定动作类型。

在下面的示例中,我正在调度 setRegistrationData,它是一个 reducer 而不是 action creator。

一些代码示例,看看我的代码是否不正确而不是我的理解:

调度reducer:

dispatch(setRegistrationData())

商店:

const store : Store = configureStore({
  reducer: {
      modalWindow: modalWindowReducer,
      yPosition : windowYPositionSlice,
      loginData: loginDataSlice,
      formValidation : loginFormValidationSlice,
      registrationData : registrationDataSlice,
  }
})


// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType<typeof store.getState>;
// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
export type AppDispatch = typeof store.dispatch;
export default store;

随机切片

// interface RegistrationData
interface RegistrationData{
    userName : string;
    email : string;
    password : string;
    confirmPassword : string;
}

// Need to change it to an object
const initialState : RegistrationData = {
    userName : '',
    email : '',
    password : '',
    confirmPassword : ''
};

export const registrationData = createSlice({
    name: 'registrationData',
    initialState,
    reducers: {
            setRegistrationData(state){
                Object.assign(state, { userName : 'DData', email : 'data@data.com', password : 'dddd', confirmPassword : 'ddd'});
            }
    }
})


export const { setRegistrationData } = registrationData.actions;
export default registrationData.reducer;

使用 RTK APIs 你抽象了一些旧的 Redux 流程 (例如 Action Creators) 但在引擎盖下发生的是完全相同的旧事物。

我认为你的困惑来自于 createSlice 方法,它是 RTK 公开的最有用的 API 方法之一:

const registrationData = createSlice({
    name: 'registrationData',
    initialState,
    reducers: {
            setRegistrationData(state){
                Object.assign(state, { userName : 'DData', email : 'data@data.com', password : 'dddd', confirmPassword : 'ddd'});
            }
    }
})

这里发生的是你在 reducers 对象内部编写了一系列 micro reducers(正式命名为 case reducers,因为它们就像标准减速器的 switch 语句中的单个 case 块)。他们给出的名字,将在内部分配给自动生成action creators。 所以最终 createSlice 的结果基本上是一个包含 reduceractions 属性的对象,实际上这就是您通过 解构从切片文件中导出的内容:

export const { setRegistrationData } = registrationData.actions;

actions 对象包含 action creators,这些 case reducers 的名称写在 reducers 对象,所以当你调度 setRegistrationData:

dispatch(setRegistrationData(data))

(data) 将自动发送到 setRegistrationData case reducer 因为 action.type 在操作中是 built-in data 将成为您操作的有效负载。事实上,如果您在减速器中记录操作:

const registrationData = createSlice({
    name: 'registrationData',
    initialState,
    reducers: {
            setRegistrationData(state, action){
                console.log(action) // {type: "registrationData/setRegistrationData", payload : { userName: ..., email: ..., etc... } }
                Object.assign(state, { userName : 'DData', email : 'data@data.com', password : 'dddd', confirmPassword : 'ddd'});
            }
    }
})

您看到 action 有一个自动生成的 type,形状为 nameOfReducer/nameOfActionCreator

正如您所看到的,createSlice 方法只是为您优化了代码,让您编写的代码少了很多,但在本质上,如果您手动编写代码,它是一样的:

const myReducer = (state, action) => {
switch (action.type) {
case "registrationData/setRegistrationData": return {...state, action.payload} // no IMMER
case ... // some other types
  }
}

然后自己构建动作创建器:

const setRegistrationData = (data) => ({ type: "registrationData/setRegistrationData" , payload: data})

然后以同样的方式发送:

dispatch(setRegistrationData(data))

那是更多的代码,您不能在 createSlice 方法中使用 built-in 的 IMMER。

所以最后只是写更少的代码,更简洁,更容易阅读和维护,但它不会以任何方式改变 Redux 的工作方式和流程。