【问题标题】:React unique key prop反应独特的关键道具
【发布时间】:2016-03-03 20:51:36
【问题描述】:

我知道这个问题有很多答案,但我找不到能完全解决我的问题的答案。我收到以下错误:Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of QuestionItem. See https://fb.me/react-warning-keys for more information.

我正在为组件设置一个密钥,但我无法让警告消失。

主要组件:

renderData() {
        return this.state.data.map((data) => {
            return (
                <QuestionItem key={data._id} data={data} delete={this.deleteItem} edit={this.editItem} />
            )
        })
    }

QuestionItem 组件:

import React, { Component, PropTypes } from 'react';
import Card from 'material-ui/lib/card/card';
import CardActions from 'material-ui/lib/card/card-actions';
import CardHeader from 'material-ui/lib/card/card-header';
import CardMedia from 'material-ui/lib/card/card-media';
import CardTitle from 'material-ui/lib/card/card-title';
import FlatButton from 'material-ui/lib/flat-button';
import CardText from 'material-ui/lib/card/card-text';
import Delete from 'material-ui/lib/svg-icons/action/delete';
import ModeEdit from 'material-ui/lib/svg-icons/editor/mode-edit';
import IconButton from 'material-ui/lib/icon-button';
import Button from '../UI/Button';

class QuestionItem extends Component {

    renderTags() {
        return this.props.data.tag.map((tag) => {
            return (
                <FlatButton label={tag} />
            )
        })
    }

    renderCompany() {
        return this.props.data.company.map((company) => {
            return (
                <FlatButton label={company} />
            )
        })
    }

    edit = () => {
        this.props.edit(this.props.data);
    }

    delete = () => {
        this.props.delete(this.props.data._id);
        console.log(this.props.data._id);
    }

    render() {
        return (
            <Card style={{margin: 50}}>
                <CardTitle title={this.props.data.text} />
                <CardText>
                    {this.props.data.answer}
                </CardText>
                <CardActions>
                    { this.renderTags() }
                    { this.renderCompany() }

                    <IconButton onClick={this.delete} style={{float: 'right'}}>
                        <Delete />
                    </IconButton>
                    <IconButton onClick={this.edit} style={{float: 'right'}}>
                        <ModeEdit />
                    </IconButton>
                </CardActions>
            </Card>
        )
    }
}

export default QuestionItem;

我在这里错过了什么?

【问题讨论】:

  • 我相信您最终需要将密钥呈现为 HTML,而且看起来您并没有将其传递到 HTML 中,而是将其放在该项目上。

标签: javascript reactjs


【解决方案1】:

您需要注销data._id 并确认它们都是唯一的。或者你可以这样做:

renderData() {
  return this.state.data.map((data, index) => {
    return (
      <QuestionItem key={index} data={data} delete={this.deleteItem} edit-{this.editItem} />
    );
 });
}

正如另一个答案所指出的,其他对 map 的调用也需要将 key 属性设置为唯一值。

所以这些:

renderTags() {
    return this.props.data.tag.map((tag) => {
        return (
            <FlatButton label={tag} />
        )
    })
}

renderCompany() {
    return this.props.data.company.map((company) => {
        return (
            <FlatButton label={company} />
        )
    })
}

应该变成:

renderTags() {
    return this.props.data.tag.map((tag, index) => {
        return (
            <FlatButton key={index} label={tag} />
        );
    });
}

renderCompany() {
    return this.props.data.company.map((company, index) => {
        return (
            <FlatButton key={index} label={company} />
        );
    });
}

注意我们使用index,它是数组索引。它基本上就像 SQL 中的合成标识符。如果您实际渲染的内容已经具有唯一标识符,那么最好使用它们!例如,标签的key 属性可能只是标签——字符串本身。 key 属性支持多种类型:

react - nodes-and-elements:

key : string | boolean | number | null,

因此,如果您的标签是唯一的(我希望它们是唯一的,但显然不想假设),您可以这样做:

renderTags() {
    return this.props.data.tag.map((tag) => {
        return (
            <FlatButton key={tag} label={tag} />
        );
    });
}

您可能会考虑改用 (tag || '').toLowerCase().replace(' ', '_') 之类的方法,但我认为 React 已经在那里进行了一些操作(除了可能的字符大小写)。所以只是传递标签本身应该是好的!如果您没有运行摆脱它的版本(我认为 0.15 摆脱它),您可以检查 DOM 以查看 data-reactid。 React 开发者工具可以让你检查 0.15 的密钥。

更新

我不建议使用数组索引作为键。它会导致细微的错误。要查看实际情况,请创建一个对象数组,使用数组索引渲染它们,然后通过删除第二个元素来改变数组(并确保 React 再次渲染)。现在索引不对应于相同的对象。我的建议是始终将键设置为唯一值。在开发过程中,最好在找到一个键之前不要设置键,而不是使用数组索引,因为这样控制台上的错误会提醒您在部署/提交更改之前修复此问题。

【讨论】:

  • 请注意,错误为check the render method of QuestionItem
  • @Mathletics Hrm.. 你在 JS 控制台上没有得到更有用的错误吗?
  • 感谢您的精彩解释
  • @Cymen 你不知道,但我认为这是一个有用的信息。我的观点是,您最初的答案是针对组件的实例化,而不是它的渲染方法。 (您的更新解决了真正的问题。)
  • @Mathletics 啊!抱歉,那里有些滞后——我也在编辑,因为我错过了附加代码。我很高兴这有效。
【解决方案2】:

renderTags()renderCompany() 中有没有键的迭代器。

【讨论】:

  • 谢谢@mathletics 我错过了
猜你喜欢
  • 2016-07-21
  • 1970-01-01
  • 2022-07-14
  • 1970-01-01
  • 1970-01-01
  • 2018-09-28
  • 2017-09-23
  • 2020-08-28
  • 2021-03-20
相关资源
最近更新 更多