繁体   English   中英

在ReactJS中使用键显示列表项的正确方法是哪一种?

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

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

“键”是创建元素列表时需要包括的特殊字符串属性。

我有一个显示产品的表格,每个产品都有一个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,我的Table类是这样的( 这只是render函数 ):

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>
        );

总计,与此无关,这是有效的,它不会对表进行任何更改。 要渲染产品,请参见以下类:

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 Productdescriptionpricequantity的状态,则会收到以下警告:

警告:flattenChildren(...):遇到两个具有相同密钥的孩子。 子密钥必须唯一。 当两个孩子共享一个密钥时,将仅使用第一个孩子。

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

我已经在ES6中编写了此代码,但希望对您有所帮助。 我不知道Total组件应该是什么样,但是计算了有意义的total prop并显示了它,因此替换起来应该很简单。

至于您的问题,“关键”道具应始终是将要保留的对象的一致标识符; 将其视为用于缓存呈现的哈希值。 因此,例如,我使用了价格和名称,因为它们在应用程序中应该保持一致。

通常,列表被映射出来。 如果您的清单很长,那么最好在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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM