【问题标题】:how to sort an object alphabetically within an array, in React.js如何在 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}/>);

【问题讨论】:

    标签: javascript reactjs firebase firebase-realtime-database


    【解决方案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 functionString的方法

    在你调用的方法中

    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
      猜你喜欢
      • 2019-06-15
      • 2014-12-30
      • 1970-01-01
      • 1970-01-01
      • 2013-11-02
      • 2015-05-17
      • 2021-01-03
      • 1970-01-01
      相关资源
      最近更新 更多