在 Redux reducer 中对对象数组进行排序

Posted

技术标签:

【中文标题】在 Redux reducer 中对对象数组进行排序【英文标题】:Sorting array of objects in Redux reducer 【发布时间】:2018-02-08 08:30:20 【问题描述】:

我正在尝试对这样的数组进行排序(我的状态):

[
  
    name:"Aenean in justo ante"
  ,
  
    name:"Phasellus viverra mattis dolor"
  
]

我向reducer发送一个动作:(reducer的一部分)

case 'SORT_COLLECTION':
  return state.sort(function(a, b) 
    var nameA = a.name.toLowerCase(), nameB = b.name.toLowerCase();
    if (nameA < nameB) 
      return -1;
    
    if (nameA > nameB) 
      return 1;
    
    return 0;
  )

但它不起作用。 谁能告诉我错误在哪里?

【问题讨论】:

Sort 会改变那里的数组 Reducer 不应该改变一个状态。它必须返回一个新的状态对象,并且保持前一个状态对象不变。如果你想有排序选项,你必须向你的状态添加相应的属性(例如指定排序方向)并根据该属性的值对render()中的数据进行排序。 “它不起作用”到底是什么意思。此代码不包含任何明显的错误。 【参考方案1】:

排序功能应该可以正常工作。但是你不应该改变 reducer 中的原始状态。您可以在排序前调用state.slice() 来创建state 数组的副本。

case 'SORT_COLLECTION':
  return state.slice().sort(function(a, b) 
    var nameA = a.name.toLowerCase(),
      nameB = b.name.toLowerCase()
    if (nameA < nameB)
      return -1
    if (nameA > nameB)
      return 1
    return 0
  )

当然,您也可以定义一个更简单的排序函数。

const state = [name:'foo',name:'bar',name:'baz']
const sortByKey = key => (a, b) => a[key] > b[key] ? 1 : -1
const sorted = state.slice().sort(sortByKey('name'))
console.log(`state=$JSON.stringify(state)\nsorted=$JSON.stringify(sorted)`)

【讨论】:

Array.slice 不做深拷贝,因此如果你有一个嵌套的数据结构,你仍然引用原始状态 @JoeSeifi 是的。子对象的状态没有改变,只有它们的顺序。这里没有理由更喜欢深度复制。【参考方案2】:

你需要做的:

state.slice().sort(...

sort() 通过重新排序引用(对其进行变异)来更改原始数组,这对于 redux 存储来说是“不行的”。 slice() 首先进行浅复制,这意味着只复制引用并且它很快(除非它包含原语,在这种情况下它们将被复制,但它仍然会很快),然后这些新引用被 sort() 移动。

注意:您仍然无法更改数组中的对象,但幸运的是 sort 不会更改它们。

【讨论】:

【参考方案3】:

Array.prototype.sort 方法要求您返回 integerboolean

下面显示了如何在任一方向订购。

var arr = [
        
            name:"Aenean jon justo ante"
        ,
        
            name:"Aenean in justo ante"
        ,
        
            name:"Phasellus viverra mattis dolor"
        
]

console.log("Alphabetical:", arr.sort((a,b) => a.name > b.name));
console.log("Reversed:", arr.sort((a,b) => a.name < b.name));

【讨论】:

你读过你链接的文章吗? compareFunction 可以返回任何数字,而不是truefalse【参考方案4】:

如果你使用的是 es6,你可以这样尝试 state.sort((a,b) =&gt; a.name - b.name);

【讨论】:

以上是关于在 Redux reducer 中对对象数组进行排序的主要内容,如果未能解决你的问题,请参考以下文章

在redux中对redux中的数据进行排序

Redux: Reduced - 如何在嵌套数组的递归过程中避免对象不可扩展错误?

在 Redux Reducer 或组件的 ShouldComponentUpdate 中进行深度比较?

Reducer 状态没有被新对象更新 [redux, redux-toolkit, normalize]

如何在 React native redux 的 reducer 中向数组添加元素?

Redux 在存储中返回一个空数组 - Reducer 无法正常工作?