这是在ReactJS中使用键显示列表项的正确方法

Whichis the correct way to display items from a list using keys in ReactJS?

本文关键字:列表 方法 显示 ReactJS      更新时间:2023-09-26

我要做的是创建一个产品列表,并在产品进入时连续显示它。为此,我使用键(来区分产品)。从React文档中我们知道:

"key"是一个特殊的字符串属性,在创建元素列表时需要包含。

我有一个显示产品的表,每个产品都有ID、描述、价格和数量(列表中该类产品的数量)。每次将新产品添加到列表时,它必须在最后一个产品显示之后显示它,但是,如果产品已经在列表中,它必须更改对象数据以显示新值。例子:

------------------------------------
| Description |  Price  | Quantity |
------------------------------------
|  Milk       |   $2.49 |     1    |
------------------------------------

所以,例如,当添加咖啡时,它应该是这样的:

------------------------------------
| Description |  Price  | Quantity |
------------------------------------
|  Milk       |   $2.49 |     1    |
------------------------------------
|  Coffee     |   $1.25 |     1    |
------------------------------------

但是,当添加另一种牛奶时,值应该是:

------------------------------------
| Description |  Price  | Quantity |
------------------------------------
|  Milk       |   $4.98 |     2    |
------------------------------------
|  Coffee     |   $1.25 |     1    |
------------------------------------
到目前为止,使用ES5,我有这样的表类(这只是渲染函数):
return (
            <div className="data">
                <div className="col-md-6">
                    <table id="table" className="table">
                        <thead>
                            <th>Description</th>
                            <th>Price</th>
                            <th>Quantity</th>
                        </thead>
                        <tbody>
                            {<Product key={key} description={description} price={price} quantity={quantity} />}
                        </tbody>
                    </table>
                </div>
                <div className="col-md-6 col-centered">
                    <div className="row"><Total key={total} total={total} /></div>
                    <div className="row">
                        <button href="#" className="btn btn-default btn-lg">Pagar</button>
                    </div>
                </div>
            </div>
        );

Total,对于这个,是不相关的,它是工作的,它不会对表做任何改变。要渲染Product,下面是类:

var Product = React.createClass({
    propTypes: {
        quantity: React.PropTypes.number.isRequired,
        description: React.PropTypes.string.isRequired,
        producttotal: React.PropTypes.number.isRequired
    },
    getInitialState: function () {
        return{
            quantity: this.props.quantity,
            description: this.props.description,
            producttotal: this.props.producttotal
        };
    },
    render: function () {
        return (
            <tr>
                <td>{this.props.quantity}</td>
                <td>{this.props.description}</td>
                <td>{this.props.producttotal}</td>
            </tr>
        )
    }
});

现在React所做的是覆盖每个项目时,它进入列表。正如您所看到的,Product获得一个键(即产品ID),但是React文档说:

键帮助React识别哪些项被更改、添加或删除了。为了给数组中的元素提供一个稳定的标识,应该给数组中的元素赋键。

当我使用props时发生这种情况,但例如,如果我用this.setState改变Product上的description, pricequantity的状态,那么我得到这个警告:

警告:扁平化儿童(…):遇到两个具有相同键的孩子。子键必须是唯一的;当两个子节点共享一个密钥时,只有第一个子节点会被使用。

那么,在ReactJS中使用键从列表中显示项目的正确方法是什么?我在React文档和论坛中找不到太多帮助。顺便谢谢。

我是在ES6中写的,但希望这能有所帮助。我不知道Total组件应该是什么样子,但是计算了有意义的total道具并显示了它,所以它应该很容易替换。

至于你的问题,"key"道具应该始终是将持久存在的对象的一致标识符;可以将其视为用于缓存呈现的散列值。例如,我使用了价格和名称,因为它们在应用程序中应该是一致的。

通常,列表是映射出来的。如果你有一个很长的列表,在componentWillReceiveProps中计算这些可能是一个好主意,以加快速度,但说实话,你应该使用像FLUX这样的东西,数据存储最终会照顾它。

无论如何,这都是一个非常粗糙和不完整的示例,但是当给定一列商品作为描述字符串列表时,映射出产品的表可以与您提供的示例一起使用:

import React, {Component} from 'react'
import Product from './Product'
// basic mock data to work with
var items = ['Milk', 'Coffee', 'Milk', 'Coffee', 'Rice-cakes', 'Coffee'];
const Products =
[
    { description : 'Milk',       price : 2.49 },
    { description : 'Coffee',     price : 1.25 },
    { description : 'Rice-cakes', price : 1.49 }
];
class Table extends Component
{
    render ()
    {
        let productList = Products.map((product)=>
        {
            let quantity = items.filter((item)=>(item == product.description)).length,
                listItem =
                {
                    key         : (product.description + product.price), //any consistent hash will do here
                    description : product.description,
                    quantity,
                    price : (product.price * quantity)
                };
            return listItem;
        });
        let total = productList.map((p)=>p.price).reduce((a, b)=>(a+b),0);
        return (
            <div className="data">
                <div className="col-md-6">
                    <table id="table" className="table">
                        <thead>
                        <th>Description</th>
                        <th>Price</th>
                        <th>Quantity</th>
                        </thead>
                        <tbody>
                        {productList.map((p)=>(<Product {...p} />))}
                        </tbody>
                    </table>
                </div>
                <div className="col-md-6 col-centered">
                    <div className="row">{total}</div>
                    <div className="row">
                        <button href="#" className="btn btn-default btn-lg">Pagar</button>
                    </div>
                </div>
            </div>
        );
    }
}
export default Table
相关文章: