【问题标题】:How would I sort a prop of an array of objects nondestructively Reactjs?我将如何非破坏性地对 Reactjs 对象数组的道具进行排序?
【发布时间】:2021-12-31 04:50:01
【问题描述】:

所以我试图通过使用状态对对象数组进行非破坏性的字母顺序排序,因此我也可以将数组返回到其原始排列。我已经尝试了很多将原始数组复制到新数组中进行排序的方法:JSON methods to carry a deep copy of this.props.getDaycare.toddlers:

 constructor(){
        super()
        this.state = {
            newArray: []
        }
        
    }

    sort = () => {
        let initialArray = this.props.getDaycare.toddlers
        let copiedInitialArray = JSON.parse(JSON.stringify(initialArray));
        console.log(copiedInitialArray)
        this.setState({
                newArray: copiedInitialArray.sort((t,u) =>{
                if (t.name < u.name) {return -1;}
                if (t.name > u.name) {return 1;}
                return 0;
               })
        })
    
    }

这似乎不起作用。它根本没有更新 DOM,但是当我单击排序按钮时,它在控制台中(按字母顺序)更新了

0: {id: 84, name: 'Jared Leno', birthday: '2019-09-02', contact: 'Poppy Roberts', phone: 7605551919, …}
1: {id: 88, name: 'Massimo Gandolfini', birthday: '2019-01-06', contact: 'Poppy Roberts', phone: 7605551919, …}
2: {id: 87, name: 'Rosie Perez', birthday: '2018-12-22', contact: 'Poppy Roberts', phone: 7605559091, …}
3: {id: 80, name: 'Samantha Madison', birthday: '2019-01-06', contact: 'Olusoji Akinremi', phone: 7605551919, …}
4: {id: 90, name: 'Sara Waters', birthday: '2018-12-22', contact: 'Jessica Smith', phone: 7605559091, …}
5: {id: 83, name: 'Serena Williams', birthday: '2019-01-06', contact: 'Sara Reynolds', phone: 7605551919, …}
length: 6
[[Prototype]]: Array(0)

我也尝试过浅拷贝方法,例如spreadslicefrom。请注意,不更新 DOM 而是在控制台中输出的结果相同。我已经在网上到处寻找这个特定问题,但我还没有看到任何示例显示如何有效地深度复制对象数组以进行排序。所有示例都对原始数组具有破坏性。

我想知道有什么办法吗?请帮忙。

【问题讨论】:

    标签: javascript arrays reactjs sorting javascript-objects


    【解决方案1】:
    1. 要复制一个 JS 数组,你可以使用Array#slice 方法。你不需要深拷贝,因为 React 中的值应该是不可变的。
    2. 我相信您的问题出在其他地方。我的猜测是你混淆了 props 和 state,这会导致无法按照你的意愿更新 DOM。要确定,您必须提供 render 方法。
    3. 在这种情况下,推荐的方法是在要排序时不要修改状态,而是在render 阶段/函数期间对元素进行排序。

    像这样:

    const cmp = (a, b) => (a > b) - (a < b);
    class SortedList extends React.Component {
        constructor(props) {
        super(props)
        this.state = {
            sort: { field: 'name', descending: false },
        };
      }
      render() {
        const { field, descending } = this.state.sort;
        const mul = descending ? -1 : 1;
        const items = this.props.items.slice();
        items.sort((a, b) => mul * cmp(a[field], b[field]));
        return (
          <ul>
            {items.map(({id, name}) => <li key={id}>{name}</li>)}
          </ul>
        );
      }
    }
    

    【讨论】:

      【解决方案2】:

      在 react 中,您应该将呈现的内容视为 propsstate 的函数。

      因此无需将排序后的数组设置为状态,只需将sortTypesortDirection 和其他可能影响列表排序方式的因素设置。

      const List = ({ data }) => {
        const [sortType, setSortType] = useState("name"); //name | birthday | contact
        const [sortDirection, setSortDirection] = useState("ASC"); //ASC | DESC
      
        const sortBy = (a, b) => {
          if (sortDirection === "ASC") {
            return (a[sortType] > b[sortType]) - (a[sortType] < b[sortType]);
          }
          return (b[sortType] > a[sortType]) - (b[sortType] < a[sortType]);
        };
      
        const handleChange = (e) => {
          const { value, name } = e.target;
          if (name === "sortType") {
            setSortType(value);
          }
          if (name === "sortDirection") {
            setSortDirection(value);
          }
        };
      
        return (
          <div>
            <h2>List</h2>
            <form onChange={handleChange}>
              <fieldset>
                <legend>Sort by</legend>
                <label>
                  Name
                  <input
                    type="radio"
                    name="sortType"
                    value="name"
                    defaultChecked={true}
                  />
                </label>
                <label>
                  Birthday
                  <input type="radio" name="sortType" value="birthday" />
                </label>
                <label>
                  Contact
                  <input type="radio" name="sortType" value="contact" />
                </label>
              </fieldset>
              <fieldset>
                <legend>Direction</legend>
                <label>
                  Ascending
                  <input
                    type="radio"
                    name="sortDirection"
                    value="ASC"
                    defaultChecked={true}
                  />
                </label>
                <label>
                  Descending
                  <input type="radio" name="sortDirection" value="DESC" />
                </label>
              </fieldset>
            </form>
      
            <ul>
              {data.sort(sortBy).map((d, i) => (
                <ListItem data={d} key={i} />
              ))}
            </ul>
          </div>
        );
      };
      

      【讨论】:

      • 你正在改变作为道具提供的data,这不是正确的 React 用法。
      • Props 在 react 中是不可变的。
      猜你喜欢
      • 2015-12-27
      • 2014-12-06
      • 2020-05-25
      • 1970-01-01
      • 2021-06-22
      • 2016-03-04
      • 1970-01-01
      • 2019-08-31
      • 1970-01-01
      相关资源
      最近更新 更多