警告:flattenChildren(...):遇到两个孩子 [英] Warning: flattenChildren(...): Encountered two children

查看:41
本文介绍了警告:flattenChildren(...):遇到两个孩子的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看过同样的问题,但无法弄清楚我的错误在哪里.

我的实时搜索框效果很好,但是一旦您删除了搜索查询(单词),react 控制台中就会显示警告:

<块引用>

警告:flattenChildren(...):遇到两个孩子键,.$1.子键必须是唯一的;当两个孩子共用一把钥匙时,只会使用第一个孩子.

这是我的整个 jsx 文件:

var SearchBox = React.createClass({做搜索:功能(){//为较新版本的 reat-rails 1.4.x 删除 .getDOMNode()var query = (this.refs.searchInput.value).toLowerCase();//这是搜索文本this.props.doSearch(查询);},渲染:函数(){return <input type="text" ref="searchInput" placeholder="搜索标题、国家和城市" value={this.props.query} onChange={this.doSearch}/>}});var DisplayTable = React.createClass({渲染:函数(){//使卡片显示var 卡片=[];var default_url = "/assets/profile_avatar/thumb/missing.png";this.props.data.map(function(s) {卡片推送(<a href={'/users/' + s.user.id + '/supports/' + s.id} key={s.id}><div className="card"><div className="row"><div className="small-5 large-6 columns"><h5>{s.support_title}</h5>

<div className="fi small-3 large-3 columns">奖励:{s.reward_after_support}

<div className="small-4 large-3 columns talr">{s.remote_support == 'on' ?'远程/任何地方':s.city + ', '+ s.country}

<小时/><div className="cl"><img className="profile-img" src={ s.profiles[0].avatar_file_name === null ?default_url : s.profiles[0].avatar_url}></img><span>{s.profiles[0].first_name}</span>

<div className="cr">申请:{s.interest_recieved} |发布:{moment(s.created_at).fromNow()}

</a>)});//返回卡片返回(<div>{牌}

);}});var InstantBox = React.createClass({doSearch:功能(查询文本){//console.log(queryText)//获取查询结果var queryResult=[];this.props.data.map(function(s){if(s.support_title.toLowerCase().indexOf(queryText)!=-1) {queryResult.push(s);}如果(s.city != null){if(s.city.toLowerCase().indexOf(queryText)!=-1) {queryResult.push(s);}}如果(s.country != null){if(s.country.toLowerCase().indexOf(queryText)!=-1) {queryResult.push(s);}}});this.setState({查询:查询文本,过滤数据:查询结果})},getInitialState:function(){返回{询问:'',过滤数据:this.props.data}},渲染:函数(){返回 (<div className="InstantBox"><div className="搜索"><SearchBox query={this.state.query} doSearch={this.doSearch}/>

<DisplayTable data={this.state.filteredData}/>

);}});

我真的没有看到问题.我错过了什么吗?

解决方案

您代码中的怪癖是 indexOf()!=-1 仅在传递的字符串不为空时才有效.所以

'Milan'.indexOf('M')//= 0'米兰'.indexOf('Q')//= -1'米兰'.indexOf('')//= 0 !!

因此,如果您的搜索字符串为空,doSearch()实际上会将包含任何城市的所有记录添加到搜索结果中,并且添加相同的记录(如果它也有)任何国家.

最后一点会导致搜索结果中包含多个具有相同 ID 的项目.而 react 不喜欢那样.

另外:如果你有一个城市=巴黎"的记录,国家是法国",那么你搜索r"的查询将导致同样的错误.字母r"在城市 -> 记录被添加.字母r"也在国家/地区 -> 将再次添加相同的记录.

完整方案还需要保证每条记录只添加一次:

if ( queryText == ''//如果没有搜索,则显示所有||s.support_title.toLowerCase().indexOf(queryText)!=-1||(s.city && s.city.toLowerCase().indexOf(queryText)!=-1)||(s.country && s.country.toLowerCase().indexOf(queryText)!=-1) ){queryResult.push(s);}

这确保每条记录只添加一次.

旁注:您填写卡片的方式可以简化,并且有一些不必要的代码.你也可以这样做:

cards = this.props.data.map(function(s) {<一个...});

I have looked at this same issue but could not figure out where my error is.

My live search box works great but once you have removed your search query (word) the warning shows up in the react console:

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

This is my entire jsx file:

var SearchBox = React.createClass({
    doSearch:function(){
      // remove .getDOMNode() for newer version of reat-rails 1.4.x
      var query = (this.refs.searchInput.value).toLowerCase(); // this is the search text
      this.props.doSearch(query);
    },
    render:function(){
        return <input type="text" ref="searchInput" placeholder="Search title, country and city" value={this.props.query} onChange={this.doSearch}/>
    }
});

var DisplayTable = React.createClass({
    render:function(){
        //making the cards to display
        var cards=[];
        var default_url = "/assets/profile_avatar/thumb/missing.png";
        this.props.data.map(function(s) {
          cards.push(
            <a href={'/users/' + s.user.id + '/supports/' + s.id} key={s.id}>
              <div className="card">
                <div className="row">
                  <div className="small-5 large-6 columns">
                    <h5>{s.support_title}</h5>
                  </div>
                  <div className=" fi small-3 large-3 columns">
                    Reward: {s.reward_after_support}
                  </div>
                  <div className="small-4 large-3 columns talr">
                     {s.remote_support == 'on' ? 'Remote / Anywhere' : s.city + ', '+ s.country}
                  </div>
                  <hr />
                  <div className="cl">
                    <img className="profile-img" src={ s.profiles[0].avatar_file_name === null ? default_url : s.profiles[0].avatar_url}></img><span>{s.profiles[0].first_name}</span>
                  </div>
                  <div className="cr">
                    Applications: {s.interest_recieved} |
                    Posted: {moment(s.created_at).fromNow()}
                  </div>
                </div>
              </div>
            </a>
           )
        });
        //returning the card
        return(
          <div>
            {cards}
          </div>
        );
    }
});

var InstantBox = React.createClass({
    doSearch:function(queryText){
        //console.log(queryText)
        //get query result
        var queryResult=[];
        this.props.data.map(function(s){
          if(s.support_title.toLowerCase().indexOf(queryText)!=-1) {
            queryResult.push(s);
          }
          if (s.city != null) {
            if(s.city.toLowerCase().indexOf(queryText)!=-1) {
              queryResult.push(s);
            }
          }

          if (s.country != null) {
            if(s.country.toLowerCase().indexOf(queryText)!=-1) {
              queryResult.push(s);
            }
          }
        });

        this.setState({
            query:queryText,
            filteredData: queryResult
        })
    },
    getInitialState:function(){
        return{
            query:'',
            filteredData: this.props.data
        }
    },
    render:function(){
        return (
            <div className="InstantBox">
              <div className="search">
                <SearchBox query={this.state.query} doSearch={this.doSearch}/>
              </div>
                <DisplayTable data={this.state.filteredData}/>
            </div>
        );
    }
});

I really dont see an issue. Am I missing something?

解决方案

The quirk in your code is that the indexOf()!=-1 only works if the passed string is not empty. So

'Milan'.indexOf('M') // = 0
'Milan'.indexOf('Q') // = -1
'Milan'.indexOf('') // = 0 !!

So if your search string is empty, the doSearch()will actually add all records with any city to the search results AND add the same record if it also has any country.

This last bit causes search results with multiple items with the same id. And react does not like that.

Also: if you have a record with city = "Paris", and country is "France", then you search query of "r" will lead to the same error. The letter "r" is in city -> record is added. Letter "r" is also in country -> same record will be added again.

Full solution also needs to ensure that each record is only added once:

if ( queryText == '' // if no search, then show all
  || s.support_title.toLowerCase().indexOf(queryText)!=-1
  || (s.city && s.city.toLowerCase().indexOf(queryText)!=-1)
  || (s.country && s.country.toLowerCase().indexOf(queryText)!=-1) ){
    queryResult.push(s);
  }

This ensures each record is added only once.

Sidenote: the way you fill your cards could be simplified, and has some unnecessary code. You could also do:

cards = this.props.data.map(function(s) {
  <a ...
});

这篇关于警告:flattenChildren(...):遇到两个孩子的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆