【问题标题】:React Redux Reducers and Immutable UpdatesReact Redux Reducers 和不可变更新
【发布时间】:2021-08-18 00:56:47
【问题描述】:

在更新配置文件值的先前场景中,我创建了一个新的存储切片 (updatedProfileDetails) 并在那里存储了一个新对象,但我认为这不是解决我的问题的最佳实践(因为我现在有两个切片 profileDetails & updateProfileDetails),

现在我在 redux 文档中发现,我们可以制作不可变的更新减速器来更改同一切片中的数据而无需改变状态,但在这种情况下(将未见会话设置为 false),API 不会发送对象作为响应,而是只是一条成功消息,


所以,我正在尝试将我的对话 ID 从 Action 传递给 reducer 以检查它并更改此对话的单个值[id]

但我无法正确完成

我的代码: 1- 操作:操作成功后我应该发送 id 的位置

export const updateSeenConversation = (id) => async (dispatch, getState) => {
  try {
    dispatch({
      type: SEEN_CONVERSATIONS_REQUEST,
    })

    const {
      userLogin: { userInfo },
    } = getState()

    const config = {
      headers: {
       // headers
      },
    }

    const { data } = await axios.put(
      `${process.env.REACT_APP_API_KEY}/conversation/unseen/${id}`,
      "",
      config
    )
// if success data : {success:true , message:"..."}

    dispatch({
      type: SEEN_CONVERSATIONS_SUCCESS,
      payload: id,  // usually i send data sent from API as dispatch payload,, to check for the exact conversation to update i tried to send id
    })

  } catch (error) { //error...})
  }
}

2- 我的减速机:

export const conversationsListReducer = (
  state = { conversations: {} },
  action
) => {
// get conversations works Fine and return a slice conversations{..} that i need to update
  switch (action.type) {
    case GET_CONVERSATIONS_REQUEST:
      return { ...state, loading: true }
    case GET_CONVERSATIONS_SUCCESS:
      return { loading: false, conversations: action.payload }
    case GET_CONVERSATIONS_FAIL:
      return { loading: false, error: action.payload }

// here ERROR
// i cant access the exact value i want "unseen" **NB:CHECK store in IMAGE BELLOW**
    case SEEN_CONVERSATIONS_REQUEST:
      return { ...state, loading: true }
    case SEEN_CONVERSATIONS_SUCCESS:
      return {state.conversations.conversation.map((conversation) => {
        if (conversation._id !== action.payload) {
          return conversation  // return without change if !== myid
        }
        return {
          ...conversation,   // make a copy 
          unseen: false,     // change this value to false/true
        }
      })}
    case SEEN_CONVERSATIONS_FAIL:
      return { loading: false, error: action.payload }
    case USER_LOGOUT:
      return { conversations: {} }
    default:
      return state
  }
}

Redux store Slice Image Link

谢谢。

【问题讨论】:

  • 您有什么问题或有什么问题(如果有的话)?
  • @DrewReese 就像我说的那样,我的第二个代码(reducer)不起作用我无法对这部分存储使用 redux 不可变更新,我正在尝试更新对话的价值.conversation["id sent from action"]['unseen'] unseen: false 来自我创建切片对话的同一个减速器

标签: reactjs redux react-redux axios


【解决方案1】:

好的,我仍然看不到您在帖子中的哪个位置说什么不起作用,但我正在收集它是 SEEN_CONVERSATIONS_SUCCESS 减速器案例中的东西,因为这是您关注一些 cmets 的地方。

据我所知,在这个 reducer 案例中,您正在将状态不变量从 { conversations: {} } 更改为 { [] },因为映射返回一个数组,并且不是有效对象。更新状态时,您需要浅拷贝状态对象以及任何正在更新的嵌套状态。

case SEEN_CONVERSATIONS_SUCCESS:
  return {
    ...state, // <-- shallow copy state
    conversations: {
      ...state.conversations // <-- shallow copy state.conversations
      conversation: state.conversations.conversation.map(  // <-- shallow copy conversation array
        conversation => conversation._id === action.payload
          ? {
            ...conversation, // <-- shallow copy conversation
            unseen: false
          }
          : conversation
      ),
    }
  };

由于此 reducer 案例正在访问可能未定义的嵌套状态属性,因此您还应该完全声明您的状态。

const initialState = {
  conversations: {
    conversation: [], // <--- now access this deep won't throw error
  },
  loading: false,
  error: null,
};

export const conversationsListReducer = (
  state = initialState,
  action
) => {
  ...

  case USER_LOGOUT:
    return initialState; // <-- reset to initial state

【讨论】:

  • 这正是我一直在寻找的,如何在不改变初始值的情况下正确访问该值,谢谢您的宝贵帮助
  • @RamziOMARI 如果您还没有研究过,我强烈建议redux-toolkit 添加到您的代码库中。它(1)删除了 react-redux cruft/boilerplate(定义动作类型和创建者、reducers 等),(2)在后台使用 immer.js 编辑 reducer 案例中的草稿副本,因此您可以只编写逻辑这会更新您想要的内容,并且切片处理不变性,并且 (3) 它生成的减速器可以毫无问题地组合到您现有的减速器树中。它是由创建 Redux 和 React-Redux 的同一团队编写的。
  • 是的,我昨天才发现它,当我了解它的工作原理后,我一定会使用它。再次感谢
  • @RamziOMARI 当我将它集成到现有且相当成熟(3 年以上)的生产应用程序中时,我已经用工具包的 configureStore 完全替换了旧的 createStore 并且有一个新的状态切片可以正常工作大约20分钟;我们所有现有的 action/reducers 和单元测试仍然按预期工作。我非常惊讶它比旧的 React-Redux 代码更容易使用。升级是值得的。
  • 啊哈哈 20 分钟!太棒了,我的仍处于开发阶段(2 个月)我想现在更简单了,我很感激。
猜你喜欢
  • 2016-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-03
  • 2017-04-03
  • 1970-01-01
  • 2023-02-02
相关资源
最近更新 更多