在 Redux 状态下更新单个值

Posted

技术标签:

【中文标题】在 Redux 状态下更新单个值【英文标题】:Update single value in Redux state 【发布时间】:2021-12-24 05:36:27 【问题描述】:

我有一个页面,上面有几个组件,其中一个组件读取 redux 状态。 当 redux 对象组件发生一些变化时,它会重新加载,显示微调器并且组件上的所有数据都会更新。 但我的任务是更新 redux 对象状态中的一个值,而无需重新渲染和刷新所有内容。 例如这里是 redux 对象,它包含一个包含一些数据的对象数组。 我需要在某个对象中更新一个值state,比如说最后一个。 但我需要这样做,而不必更新所有状态。

state:
 0:
  name : 'some name.....',
  surname: 'some surname',
  age: '23',
  phone: '+12345678'
  state: 'ON' 
 ,

 1:
  name : 'some name.....',
  surname: 'some surname',
  age: '23',
  phone: '+12345678'
  state: 'ON' 
 ,

 2:
  name : 'some name.....',
  surname: 'some surname',
  age: '23',
  phone: '+12345678'
  state: 'OFF' <-- I need to update only this one 
 ,


我在 Redux 操作中有一个函数可以加载所有这些数据。

但现在我需要一个单独的函数 updateData 之类的函数,它将更新现有状态对象中的一个值,而无需刷新所有内容。

在 Redux 中可以这样做吗?

【问题讨论】:

【参考方案1】:

您需要熟悉 Redux 中 action 和 reducer 的工作方式,但是是的,这绝对是可能的。

您可以创建一个UPDATE_DATA 动作创建器,您可以在您的反应组件中调用它。您将拥有一个 reducer 来控制数据的处理方式和状态更改方式。

-编辑- 如 cmets 中所述,我在 Redux 的减速器中使用“immer”。这是我如何使用它来编辑和现有数组中的项目的示例:

case EDIT_ITEM:
      return produce(state, (draft) => 
        const index = findItemIndex(draft, action.payload._id)
        draft[index] = action.payload
      )

所以你传入状态和回调,草稿是状态对象的可变等价物。

【讨论】:

这是问题所在,如果可能的话,我真的不明白减速器应该是什么样子。假设我在减速器中有动作来加载数据。 case LOAD_ALL_USERS_SUCCES: return ...state, usersLoading: false, users: action.payload.response.users, 当我想更新它时。我在操作中使用 getState() 获取现有状态并更改属性它在减速器中应该是什么样子,所以它不会更新组件中的所有内容? Redux 中的状态是不可变的。我在最近的一个应用程序中使用了一个名为“immer”的模块,它提供了一个名为produce() 的函数。这为处理数据提供了灵活性,就好像它不是一成不变的一样。 immerjs.github.io/immer 我在答案中添加了一个示例。【参考方案2】:

您的状态是对象的对象(不是数组)。 您无法更新您所在州的单个属性。您必须提供具有更新值的新对象。研究 redux 中的不变性:https://redux.js.org/faq/immutable-data

在你的 reducer 中试试这个:

const changedVal=state[2];
changedVal.state='ON';
return ...state,changedVal;

【讨论】:

【参考方案3】:

简而言之,更新一个属性实际上是不可能的。当然做不到,但是难度很大。我可以解释原因。

让我们从更新项目开始。这绝对是可能的。假设您有一个 redux 选择器在将数据发送到组件时监听 data

  const DisplayOneItem = React.memo(( name, age ) =>  ... )

您可以看到,首先将name(和age)发送到该组件,然后应用React.memo,这样只有当其中一个属性发生更改时,它才能更新。但不要与以下行混为一谈:

  const DisplayOneItem = React.memo(( item ) =>  ... )

上面的行占用了整个item,当你改变一个属性时,item也会改变,因此无论如何,你都会得到一个新的更新。

您可能想知道如果不使用React.memo 会发生什么?是的,一直渲染。实际上,如果您更改属性,itemdata 将完全更改。否则你如何通知 React 有变化? :)

注意:React 默认情况下不能根据值的变化进行更新。它更新的原因是因为您通过setState( ...data ) 要求它。所以现在是关于粒度YOU如何控制调度(或渲染)的问题。人们可能会认为 React 在渲染方面很神奇,但实际上它只是在请求时才这样做。所以现在你的问题是,我要求它渲染,但它不应该渲染?哈哈,你明白了。

【讨论】:

以上是关于在 Redux 状态下更新单个值的主要内容,如果未能解决你的问题,请参考以下文章

React:Redux状态在一个效果中更新但在同一组件中的下一个效果是使用先前的state值

Redux (with React) Reducer switch 语句不更新状态

Redux reducer,检查状态数组中是不是存在值并更新状态

使用输入更新 redux 状态

Redux:重用reducer来更新多个状态属性

更新 redux 状态/提交表单时页面重新加载