如何在 React.js 中按字母顺序对数组中的对象进行排序
Posted
技术标签:
【中文标题】如何在 React.js 中按字母顺序对数组中的对象进行排序【英文标题】:how to sort an object alphabetically within an array, in React.js 【发布时间】:2018-06-08 10:52:47 【问题描述】:我正在使用 React.js 和 firebase 制作一个应用程序,用户可以在其中输入姓名和人的地址。
firebase 中的对象如下所示:
L1NSTjqA10Qc85d7Kcc
- name: John Doe,
- address: 1 Maple Ave
我已成功将名称和地址打印到 DOM 上,但我想按名称的字母顺序对其进行排序。
所以我的列表将如下所示:
Jane Doe - 34 Green Street
John Doe - 1 Maple Ave
Riley Smith - 3 Happy Street
到目前为止,这是我的 JSX,用于在父组件上映射对象数组时:
<ul>
this.state.contacts.map((res)=> <List data=res/>)
</ul>
以防万一,这是我的 componentDidMount:
componentDidMount()
const dbRef = firebase.database().ref();
dbRef.on("value", (firebaseData) =>
const itemsArray = [];
const itemsData = firebaseData.val();
for (let itemKey in itemsData)
itemsArray.push(itemsData[itemKey])
this.setState( contacts: itemsArray)
)
我曾尝试从另一个堆栈溢出论坛执行以下操作,但没有成功:
const myData = [].concat(this.state.contacts)
.sort((a,b)=> a.name > b.name
.map((res)=> <List data=res/>);
【问题讨论】:
【参考方案1】:您尝试排序然后映射的逻辑部分可以这样完成。
const myData = this.state.contacts
.sort(function(a, b)
if(a.name.toLowerCase() < b.name.toLowerCase()) return -1;
if(a.name.toLowerCase() > b.name.toLowerCase()) return 1;
return 0;
)
.map((item, i) => <List key=i data=item />);
或者如果你想做得更短,你可以这样做。
const myData = this.state.contacts
.sort((a, b) => a.name.localeCompare(b.name))
.map((item, i) => <List key=i data=item />);
localeCompare
function是String
的方法
在你调用的方法中
dbRef.on("value", (firebaseData) =>
this.setState(
contacts: Array.from(firebaseData.val()).sort((a, b) => a.name.localeCompare(b.name)))
);
在您的 render
方法中执行以下操作
render ()
return (
<ul>
this.state.contacts.map((item, i) => <List key=i data=item />)
</ul>
);
这有帮助吗?
【讨论】:
如何将它添加到我的 JSX 中?我试图在“返回”中输入您的简短答案,但是,它给了我错误。我应该在渲染方法之后但在返回之前添加它吗?请指教,谢谢 没关系,我想通了:我把它放在渲染方法中,在返回之前,但在jsx中调用了变量。感谢您的帮助! 无论如何我确实更新了我的答案。如果此答案对您有所帮助,请考虑将标记作为您的答案。并竖起大拇指。干杯。 @AdeelImran 你不需要这样做:itemsArray = itemsArray.sort
因为.sort
正在更改数组in place。你不应该这样做:this.state.contacts.sort
因为你正在改变状态。这就是 OP 使用 [].concat
创建新数组的原因。
明白,我也更新了那部分代码。我仍然觉得[].concat
是一种老派的方法。所以我只是使用Array.from
并对结果进行排序。【参考方案2】:
不要不要在渲染方法中对数据进行排序!它会在每次渲染调用时对其进行排序。
要记住的另一件事是sort 正在执行manipulation on the array and not returning a new copy of the array。 来自文档:
注意数组是原地排序的,不做拷贝
这意味着你将改变 state
对象,这是一个很大的反应。
这就是您使用[].concat(this.state.contacts)
创建新数组的原因。
你可以用ES2015 spread syntax实现一个新数组:
const newArray = [...this.state.contacts];
无论如何,不要处理状态的副本和突变,而是在将数组存储到状态之前进行排序:
itemsArray.sort((a,b) =>
return a.name > b.name;
);
this.setState(
contacts: itemsArray
)
【讨论】:
它不会对sort
部分执行重新渲染,除非状态再次更新。仅当您更新渲染方法时。
这不正是我写的吗? “它将在每次渲染调用时执行此操作”。顺便说一句,render
方法没有更新(它是一个将被调用的函数)。作为对象的状态将被更新。
这很简单,你有一个函数 render
在那个函数里面你正在做一些排序。每次render
被调用时,您都会再次进行此排序(可能没有充分的理由)。 render
方法将在状态的每次更新时被调用,因此 OP 可能有其他可以更新的状态数据,这将触发 render
调用,该调用将对数组进行排序再次。就像我提到的,没有充分的理由。
我明白你的意思。道歉。我已经更新了我的答案。
@AdeelImran +1 不要忘记 .sort
正在改变数组。因此,如果您直接在 state
对象上的 render
内执行此操作,您将改变 state
。【参考方案3】:
非常简单的解决方案,只需 2 个函数即可对多列应用排序。
不需要 toLowerCase ,只需使用 "" 转换成字符串
只需创建这两个函数
compareBy(key)
return function (a, b)
if (""+a[key]<(""+b[key])) return -1;
if (""+a[key]>(""+b[key])) return 1;
return 0;
;
sortBy(key)
let arrayCopy = [...this.state.data];
arrayCopy.sort(this.compareBy(key));
//arrayCopy.reverse(); for descending
this.setState(data: arrayCopy);
//write this in th
onClick=() => this.sortBy('column name')
如果你想降序使用它是升序排序 arrayCopy.reverse()
它根据 ASCII 格式排序,所以字符串使用 toLowerCase
【讨论】:
【参考方案4】:.sort((a, b) => parseFloat(a.sort) - parseFloat(b.sort))
【讨论】:
欢迎来到 Stack Overflow!虽然这段代码可以解决问题,including an explanation 解决问题的方式和原因确实有助于提高帖子的质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提问的人。请edit您的回答添加解释并说明适用的限制和假设。 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。以上是关于如何在 React.js 中按字母顺序对数组中的对象进行排序的主要内容,如果未能解决你的问题,请参考以下文章