【问题标题】:Key warning in react.jsreact.js 中的关键警告
【发布时间】:2018-10-19 02:52:44
【问题描述】:

我得到了这个:

警告:数组或迭代器中的每个子元素都应该有一个唯一的“key”属性。

这是我的下拉组件代码:

render() {
    let dropDownClasses = [classes["im-dropdown"], classes[this.state.size], classes[this.state.dropStyle], classes[this.status]];
    let itemcount = -1;
    let options;
    if(this.state.options !== undefined){
        options = this.state.options.map(option => {
            itemcount++;
            return(<div><li key ={'opt_'+this.state.name+'_'+itemcount}  role="option" aria-selected="false" value={option.value} tabIndex={itemcount} onClick={this.handleSelect.bind(this, this.state.name, option.value, option.text)}>  {option.text} </li></div>)
        });
    }

    return (
        <div className={dropDownClasses.join(' ')}>
            <button aria-haspopup="listbox" aria-expanded="false" onClick={this.handleOpen}>
                <span>{this.state.label}</span><span className={classes["caret"]}><i className="fa fa-angle-down"></i></span>
            </button>
            <ul className={classes["options"]} role="listbox" aria-labelledby={"im-drop_" +this.state.size+"_"+this.state.dropStyle} >
                <span key ={'opt_'+this.state.name+'_'+itemcount}>{options} </span>
            </ul>
        </div>
    );
}

我通过另一个组件将它称为 SideDrawer.js,如下所示:

    <div>
        <span className ={classes["filter"]}><strong>FILTER BY</strong></span>
    </div> 
    <Dropdown key={'opt_'+ clientDropdown.label} label={clientDropdown.label} name={clientDropdown.name} options={clientDropdown.options} action={props.formHandler}/>
    <Dropdown  label={typeDropdown.label} name={typeDropdown.name} options={typeDropdown.options} action={props.formHandler}/>
    <Dropdown  label={categoryDropdown.label} name={categoryDropdown.name} options={categoryDropdown.options} action={props.formHandler}/>
</div>

警告似乎即将到来,因为我在单个 div 中多次调用 Dropdown 组件(更像是一个项目数组),从而导致 Key 警告。我尝试使用“key”作为道具,但它没有_

【问题讨论】:

  • 请完成最后一个短语(我在缺少的地方添加了“_”)。我还为您改进了帖子的格式,请在您的下一个问题和/或答案中这样做。最好的问候

标签: reactjs


【解决方案1】:
  1. 不要直接在渲染中绑定函数,而是始终在构造函数中绑定函数
  2. 不要将 li 包含在 div 中
  3. 尽量保持渲染部分干净
  4. 您将密钥设置为 li 而不是 div,这就是您收到警告的原因
  5. 此外,当您执行循环时,您需要将键设置为父 jsx 元素,并且键应该来自应该唯一的数据。如果你 不要从数据中获取每个对象的唯一 ID,然后使用索引作为键 如下所示。请记住,索引始终是第二选择。

我已经尽可能地简化了你的代码

constructor(props){
  super(props);
  this.handleSelect = this.handleSelect.bind(this);
}
render() {
    const { options, name, label, dropStyle, size } = this.state;
    const dropDownClasses = [classes["im-dropdown"], classes[size], classes[dropStyle], classes[this.status]];
    return (
        <div className={dropDownClasses.join(' ')}>
            <button aria-haspopup="listbox" aria-expanded="false" onClick={this.handleOpen}>
                <span>{label}</span><span className={classes["caret"]}><i className="fa fa-angle-down"></i></span>
            </button>
            <ul className={classes["options"]} role="listbox" aria-labelledby={"im-drop_" +size+"_"+dropStyle} >
                  {Array.isArray(options) && options.length && options.map((option, index) => (
                      <li key ={`Key_${index}`} role="option" aria-selected="false" value={option.value} tabIndex={index} onClick={() => this.handleSelect(name, option.value, option.text)}>  {option.text} </li>
                  ))}
            </ul>
        </div>
    );
}

【讨论】:

  • @Rahul 欢迎您。请点赞并接受答案,以便对未来的读者有所帮助
【解决方案2】:

将键移动到父 div,您可能还想删除键后的冗余空间。您也可以使用索引参数而不是您的项目计数。

    options = this.state.options.map((option, index) => {
        return(<div key={'opt_'+this.state.name+'_'+index}><li role="option" aria-selected="false" value={option.value} tabIndex={itemcount} onClick={this.handleSelect.bind(this, this.state.name, option.value, option.text)}>  {option.text} </li></div>)
    });

【讨论】:

    【解决方案3】:

    在使用 map 函数迭代和返回任何 html 元素时,每个元素都需要唯一的 key,否则您会收到警告,因为节点元素安装在键上,但不是必须提供键,而是为了获得最佳性能并且需要零错误代码。

    在您的代码中,您应该为父元素提供密钥,因此您为子元素映射函数提供密钥不考虑为map keys

    你的代码:

    if(this.state.options !== undefined){
            options = this.state.options.map(option => {
                itemcount++;
                return(<div><li key ={'opt_'+this.state.name+'_'+itemcount}  role="option" aria-selected="false" value={option.value} tabIndex={itemcount} onClick={this.handleSelect.bind(this, this.state.name, option.value, option.text)}>  {option.text} </li></div>)
            });
        }
    

    修复代码:键应该在父元素中

    if(this.state.options !== undefined){
            options = this.state.options.map(option => {
                itemcount++;
                return(<div key ={'opt_'+this.state.name+'_'+itemcount} ><li role="option" aria-selected="false" value={option.value} tabIndex={itemcount} onClick={this.handleSelect.bind(this, this.state.name, option.value, option.text)}>  {option.text} </li></div>)
            });
        }
    

    【讨论】:

      【解决方案4】:
      if(this.state.options !== undefined){
          options = this.state.options.map((option,i) => {
              itemcount++;
              return(<div key={i}><li   role="option" aria-selected="false" value={option.value} tabIndex={itemcount} onClick={this.handleSelect.bind(this, this.state.name, option.value, option.text)}>  {option.text} </li></div>)
          });
      }
      

      当你在数组中创建一个组件时,应该在父组件中给出一个键,现在我将索引设置为一个键..希望它对你有帮助

      【讨论】:

        猜你喜欢
        • 2019-07-09
        • 1970-01-01
        • 2020-12-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-02-03
        • 2020-07-23
        相关资源
        最近更新 更多