javascript - 在 React JS 中使用键显示列表中项目的正确方法是什么?

标签 javascript html reactjs

我想做的是创建一个产品列表,并在产品进入时持续显示它。为此,我使用键(以区分产品)。来自React documentation我们知道:

A "key" is a special string attribute you need to include when creating lists of elements.

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

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得到一个 key (即产品 ID),但是 React documentation说:

Keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a stable identity.

当我使用 props 时会发生这种情况,但是例如,如果我更改 description 的状态, pricequantityProductthis.setState ,然后我收到此警告:

Warning: flattenChildren(...): Encountered two children with the same key. Child keys must be unique; when two children share a key, only the first child will be used.

那么,在 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

关于javascript - 在 React JS 中使用键显示列表中项目的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40625498/

相关文章:

javascript - 如何在 react-slick carousel 中执行 slickNext 方法?

ExtJS TreeGrid 的节点鼠标悬停事件

html - 如何使用 jquery mobile 以百分比设置 2 行高度?

html - 使用 CSS 修剪 div 中的 HTML 文本

javascript - 鼠标向上 javascript 事件未触发图像控件

javascript - 如何区分javascript对象中的url和字符串

reactjs - 在 React.js 中的耗时操作之前加载消息

javascript - 当父组件和子组件都是函数组件时,如何将函数作为 Prop 传递?

javascript - 在文档加载中运行脚本

javascript - Angular 服务的多个实例