首页 > 解决方案 > 带有钩子的 React 和 Redux

问题描述

很久没有 Redux 了,我开始生锈了。

我记得我们有 reducer 和所有应用程序状态管理的日子。

现在真的很难理解工作流程。

所以我有我的商店。

import { configureStore } from '@reduxjs/toolkit'
import userReducer from "../features/user";

export default configureStore({
  reducer: {
    user: userReducer
  },
})

这就是所谓的切片?

import {createSlice} from "@reduxjs/toolkit";

export const rootSlice = createSlice({
  name: "user",
  initialState: {
    value: {
      person_in: null,
      code: null,
      surname: null,
      name: null,
      active: null,
      token: null,
      org_unit: null,
      available_days: null,
      current_available_days: null,
      total_days: null,
      is_logged_in: false,
    }
  },
  reducers: {
    updateUser: (state, action) => {
      state.value = action.payload
    }
  }
  });

 export const { updateUser } = rootSlice.actions;

 export default rootSlice.reducer;

所以我明白了,如果我想更新我去的用户的状态

dispatch(updateUser({...});

我怎样才能只更新code属性或任何其他属性?

标签: reactjsredux

解决方案


为了实现更新初始状态对象的单个属性的能力,您还需要实现Action类型的 redux 概念。

您可以利用语句中的action.type值,switch/case以便您可以仅分支和更新您需要的内容: https ://redux.js.org/tutorials/fundamentals/part-3-state-actions-reducers#handling-additional-actions 。

我不太熟悉,reduxjs/toolkit但看起来他们createSlice以稍微不同但非常直观的方式提供了这个: https ://redux-toolkit.js.org/api/createSlice#the-extrareduces-builder-callback-notation 。在其中将extraReducers函数属性添加到createSlice对象。

这是他们的示例代码:

import { createSlice, createAction } from '@reduxjs/toolkit'
import { createStore, combineReducers } from 'redux'

const incrementBy = createAction('incrementBy')
const decrementBy = createAction('decrementBy')

const counter = createSlice({
  name: 'counter',
  initialState: 0,
  reducers: {
    increment: (state) => state + 1,
    decrement: (state) => state - 1,
    multiply: {
      reducer: (state, action) => state * action.payload,
      prepare: (value) => ({ payload: value || 2 }), // fallback if the payload is a falsy value
    },
  },
  // "builder callback API", recommended for TypeScript users
  extraReducers: (builder) => {
    builder.addCase(incrementBy, (state, action) => {
      return state + action.payload
    })
    builder.addCase(decrementBy, (state, action) => {
      return state - action.payload
    })
  },
})

const user = createSlice({
  name: 'user',
  initialState: { name: '', age: 20 },
  reducers: {
    setUserName: (state, action) => {
      state.name = action.payload // mutate the state all you want with immer
    },
  },
  // "map object API"
  extraReducers: {
    [counter.actions.increment]: (
      state,
      action /* action will be inferred as "any", as the map notation does not contain type information */
    ) => {
      state.age += 1
    },
  },
})

const reducer = combineReducers({
  counter: counter.reducer,
  user: user.reducer,
})

const store = createStore(reducer)

store.dispatch(counter.actions.increment())
// -> { counter: 1, user: {name : '', age: 21} }
store.dispatch(counter.actions.increment())
// -> { counter: 2, user: {name: '', age: 22} }
store.dispatch(counter.actions.multiply(3))
// -> { counter: 6, user: {name: '', age: 22} }
store.dispatch(counter.actions.multiply())
// -> { counter: 12, user: {name: '', age: 22} }
console.log(`${counter.actions.decrement}`)
// -> "counter/decrement"
store.dispatch(user.actions.setUserName('eric'))
// -> { counter: 12, user: { name: 'eric', age: 22} }

在他们的示例中,他们更新了计数器(单个属性)状态,并更新了用户(对象属性)状态。


推荐阅读