【问题标题】:Warning: flattenChildren(...): Encountered two children警告:flattenChildren(...):遇到两个孩子
【发布时间】:2016-01-28 05:39:13
【问题描述】:

我查看了this same issue,但不知道我的错误在哪里。

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

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

这是我的整个 jsx 文件:

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

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

【问题讨论】:

  • 消息的意思是您至少有 2 张具有相同密钥的卡。您将其定义为key={s.id}。并且 react 不允许两张卡具有相同的密钥。所以可能你需要 a) 确保每个数据记录都有一个唯一的 id,或者 b) 使用另一个变量作为唯一键

标签: javascript ruby-on-rails ruby-on-rails-4 reactjs


【解决方案1】:

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

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

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

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

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

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

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

这样可以确保每条记录只添加一次。

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

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

【讨论】:

  • 我想我已经为if (queryText.length &gt; 0... 完成了与您类似的代码,但我可能错了。您所说的非常有道理,稍后我会在使用笔记本电脑时尝试一下。今晚我会确认。谢谢。
  • 我已经稍微编辑了您的答案,谢谢!一切都很好,没有警告!
猜你喜欢
  • 2017-12-15
  • 2017-05-17
  • 2017-06-01
  • 2016-07-10
  • 2017-09-11
  • 1970-01-01
  • 2017-08-08
  • 2018-01-01
  • 1970-01-01
相关资源
最近更新 更多