【问题标题】:ReactJS won't print an array in the order that it is stored?ReactJS 不会按存储顺序打印数组?
【发布时间】:2018-08-11 04:21:25
【问题描述】:

我的 reactjs 代码存在问题,其中 render() 函数不会按照存储在状态对象中的顺序打印数组。

这是我的代码,非常简单:

import React from "react";

export default class DonationDetail extends React.Component {
  constructor(props) {
    super(props);
    this.state = { content: [] };
  }

  componentDidMount() {
    let state = this.state;
    state.content.push({ food: "burger" });
    state.content.push({ food: "pizza" });
    state.content.push({ food: "tacos" });
    this.setState(state);
  }

  addPaymentItem() {
    const item = { food: "" };
    let state = this.state;
    state.content.unshift(item);
    this.setState(state);
  }

  render() {
    console.log(this.state);
    let ui = (
      <div>
        <button type="button" onClick={() => this.addPaymentItem()}>
          add to top
        </button>
        {this.state.content.map((item, key) => (
          <input type="text" key={key} defaultValue={item.food} />
        ))}
      </div>
    );
    return ui;
  }
}

当您按下按钮add to top 时,一个新项目将放置在state.content 数组的前面,您可以从console.log(this.state) 语句中验证这一点。但不寻常的是,生成的 HTML 不会将此新项目添加到用户界面输出的顶部。相反,另一个带有单词 taco 的输入字段被放置在用户界面中列表的底部。

为什么 ReactJS 不按实际存储的顺序打印我的 state.content 数组?

【问题讨论】:

  • 您使用的状态不正确。你不应该直接改变状态对象。您想使用this.setState() 并将其传递给具有计算状态的新对象,或者传递一个返回具有更新状态的对象的函数。此外,您不想在渲染期间将整数索引用作key - 将其命名为有用的名称,例如`content-${key}`
  • @Derek - 我确实在每次对其进行变异时都使用了 setState() 。我也尝试按照您的建议更改密钥,但结果仍然相同,呈现的项目列表不反映状态的顺序。还有其他建议吗?
  • 使用数组索引作为键是一种已知的反模式,因为 react 的协调是如何工作的。点击此处了解更多详情:medium.com/@robinpokorny/…

标签: reactjs


【解决方案1】:

当数组中元素的顺序不会改变时,您可以使用数组索引key,但是当您将元素添加到数组的开头时,顺序会改变。

您可以为所有食物添加一个独特的id,并将其用作key

示例

class DonationDetail extends React.Component {
  state = { content: [] };

  componentDidMount() {
    const content = [];

    content.push({ id: 1, food: "burger" });
    content.push({ id: 2, food: "pizza" });
    content.push({ id: 3, food: "tacos" });

    this.setState({ content });
  }

  addPaymentItem = () => {
    const item = { id: Math.random(), food: "" };
    this.setState(prevState => ({ content: [item, ...prevState.content] }));
  };

  handleChange = (event, index) => {
    const { value } = event.target;
    this.setState(prevState => {
      const content = [...prevState.content];

      content[index] = { ...content[index], food: value };

      return { content };
    });
  };

  render() {
    return (
      <div>
        <button type="button" onClick={this.addPaymentItem}>
          add to top
        </button>
        {this.state.content.map((item, index) => (
          <input
            type="text"
            key={item.id}
            value={item.food}
            onChange={event => this.handleChange(event, index)}
          />
        ))}
      </div>
    );
  }
}

ReactDOM.render(<DonationDetail />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="root"></div>

【讨论】:

    【解决方案2】:

    代替:

    componentDidMount() {
      let state = this.state;
      state.content.push({ food: "burger" });
      state.content.push({ food: "pizza" });
      state.content.push({ food: "tacos" });
      this.setState(state);
    }
    

    试试

    componentDidMount() {
      this.setState(prevState => ({
        content: [
          ...prevState.content,
          { food: "burger" },
          { food: "pizza" },
          { food: "tacos" },
        ]
      }));
    }
    

    addPaymentItem() {
      const item = { food: "" };
      let state = this.state;
      state.content.unshift(item);
      this.setState(state);
    }
    

    addPaymentItem() {
      this.setState(prevState => ({
        content: [
          { food: "" },
          ...prevState.content,
        ]
      }));
    }
    

    【讨论】:

      猜你喜欢
      • 2015-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多