如何在React-Native中处理平面列表项目上的状态

时间:2019-05-31 20:05:49

标签: reactjs react-native react-native-flatlist react-state-management

我正在React-Native的FlatList组件的项目上设置一个计数器。每当用户按下“ +”或“-”按钮时,如何更新列表项?

我目前能够更新状态值,但是列表不显示新状态。我曾尝试将extraData组件添加到FlatList,但是无论如何它似乎都没有更新。

这是数据结构

      data: [
        {
          id: 1,
          name: "Bread",
          price: "400",
          imageS: "../resources/pan-corteza-blanda.jpg",
          quantity: 2
        },
... more data

这是处理增量的功能

  handleIncrement = i => {
    this.setState(state => {
      const formatData = state.data.map((item, j) => {
        console.log("Id", i + " /// " + item.id);
        if (item.id === i) {
          item.quantity = item.quantity + 1;
          return item;
        } else {
          return item;
        }
      });
      console.log("FormatData" + formatData); //Displays the correct  quantity of the item updated

      return {
        formatData
      };
    });
  };

这是列表组件

  <FlatList
          data={this.state.data}
          style={styles.list}
          extraData={this.state.data}
          renderItem={this.renderItem}
        />

我希望每次用户按下“ +”或“-”按钮时,用正确的数量值更新列表项的文本部分。

2 个答案:

答案 0 :(得分:0)

this.state.data从未在您的handleIncrement上更改过,这就是您要传递给FlatList的内容。这就是FlatList不更新的原因。

handleIncrement运行后,状态唯一改变的是:

{
  formatData: [...stuff here]
}

也许您想传递this.state.formatData或在handleIncrement中将其重命名为data

此外,您的状态结构可能更适合作为映射,其中键为itemIds。这样,您每次想增加数量时都不需要映射整个列表。

例如

  {

    1: {
      id: 1,
      name: "Bread",
      price: "400",
      imageS: "../resources/pan-corteza-blanda.jpg",
      quantity: 2
    },
    // more data...
  }

现在,您的handleIncrement如下所示:

handleIncrement = itemId => this.setState(prevState => ({
  ...prevState,
  [itemId]: ++prevState[itemId].quantity
}))

答案 1 :(得分:0)

您需要更新数据状态而不是返回项目。

handleIncrement = i => {

  const item = this.state.data[i];

  this.setState({
    data: [
      ...this.state.data.slice(0, i),
      Object.assign({}, this.state.data[i], { quantity: item.quantity + 1 }),
      ...this.state.data.slice(i + 1)
    ]
  });
};

您可以重构该函数并将其用于-+

// pass array index and quantity 1 for + and -1 for -
handleIncrement = (i, qty) => {
  const item = this.state.data[i];

  if (item && item.quantity === 0 && qty === -1) {
    return;
  }

  this.setState({
    data: [
      ...this.state.data.slice(0, i),
      Object.assign({}, this.state.data[i], { quantity: item.quantity + qty, }),
      ...this.state.data.slice(i + 1),
    ],
  });
};

下面是使用上述功能的演示,它在reactjs中。该功能也可以在本机反应中使用。

h1, p {
  font-family: Lato;
}

.container {
  display: flex;
  flex-direction: row;
  border-bottom-style: solid;
  margin-bottom: 5px;
}

.image-container {
  flex-grow: 0;
}

.info-container {
  display: flex;
  margin-left: 10px;
  flex-direction: row;
}

.title {
  margin-top: 0;
}

.titleContainer {
  width: 100px;
}

.cover {
  width: 30px;
}

.buttons {
  flex-grow: 1;
  display: flex;
  margin-left: 10px;
}

.incrementButtons {
  width: 20px;
  height: 20px;
  margin-left: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.0/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.21.1/babel.min.js"></script>
<div id="root"></div>

<script type="text/babel">

class Item extends React.Component {
  render() {
    return (
      <div className="container">
        <div className="image-container">
          <img className="cover" src={this.props.image} />
        </div>
        <div className="info-container">
          <div className="titleContainer">
            <p className="title">{this.props.title}</p>
          </div>
          <div className="buttons">
            <p className="title">{this.props.qty}</p>
            <img onClick={() => this.props.increment(this.props.index, -1)} className="incrementButtons" src="https://img.icons8.com/metro/26/000000/minus-math.png" />
            <img onClick={() => this.props.increment(this.props.index, 1)} className="incrementButtons" src="https://img.icons8.com/metro/26/000000/plus-math.png" />
          </div>
        </div>
      </div>
    )
  }
}

class App extends React.Component {

  state = {
    data: [
      {
        id: 1,
        name: 'Avocado',
        price: '400',
        imageS: 'https://img.icons8.com/metro/26/000000/avocado.png',
        quantity: 0,
      },
      {
        id: 6,
        name: 'Bread',
        price: '300',
        imageS: 'https://img.icons8.com/metro/26/000000/bread.png',
        quantity: 0,
      },
      {
        id: 2,
        name: 'Milk',
        price: '300',
        imageS: 'https://img.icons8.com/metro/26/000000/milk-bottle.png',
        quantity: 0,
      },
    ],
  };

  handleIncrement = (i, qty) => {
    const item = this.state.data[i];

    if (item && item.quantity === 0 && qty === -1) {
      return;
    }

    this.setState({
      data: [
        ...this.state.data.slice(0, i),
        Object.assign({}, this.state.data[i], { quantity: item.quantity + qty, }),
        ...this.state.data.slice(i + 1),
      ],
    });
  };

  render() {

    const items = this.state.data.map((item, index) => (
      <Item qty={item.quantity} index={index} key={index} increment={this.handleIncrement} title={item.name} image={item.imageS} />
    ))
    return (
      <div>
        {items}
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById('root'));
</script>