无法从json,react-redux访问儿童

时间:2017-09-19 04:58:46

标签: reactjs redux react-redux children

嗨,我可以访问联系人姓名Ron并在其中使用过滤器。但是,我无法访问孩子联系Alex并在过滤器中使用它。我附上了输出截图。我需要在其中打印儿童Alex并使用过滤器。提前谢谢

        import React, {Component} from 'react';
        import ReactDOM from 'react-dom';

        let arr = [{"id":1,
        "number":true,
        "location":"2",
        "time":11,
        "code":1001,
        "name":"Ron",
            "children":[{
                "id":141,
                "number":true,
                "location":1,
                "time":1504969439000,
                "code":null,
                "name":"Alex"}]}]

      const Tab = ({ value }) => <div> {value} </div>;

      class App extends React.Component {
                constructor() {
                    super();
                    this.state ={
                        search: ''
                    };
                }
                updateSearch(event){
                    this.setState({search: event.target.value.substr(0,20)})
                }


        render() {
            let filteredContacts = arr.filter((item)=>{
            return item.name.toLowerCase().indexOf(this.state.search)!==-1;
            });

            return(<div> 
                <h1> Contact List </h1>
                <input type="text" 
                       value={this.state.search} 
                       placeholder="Search Here" 
                       onChange={this.updateSearch.bind(this)}  />
              <ul>
              {
                filteredContacts.map((obj, i) => 
                <Tab value={obj.name} key={i} />)
              }
             </ul>
             </div>
        );
      }
    }
    ReactDOM.render(<App/>, document.getElementById('container'));

Output

1 个答案:

答案 0 :(得分:1)

您的过滤只会遍历数组中的第一级联系人,因此.children中的所有联系人都不会被显示或过滤掉。

你想要做的是创建一个包含所有联系人的数组,但是将它们放在同一个“底部”级别([{name: 'Ron'}, {name: 'Alex'}]),以便我们可以过滤 而不是数组。

这样做的一种方法是首先.map超过原始数组,并确保我们同时获得“底部”(父)联系人和一个数组中的子项:(如果...语法对你而言是新的,scroll to 'Spread in array literals' here

const allContacts = originalContacts.map(parentContact => [parentContact, ...parentContact.children])

但是这会让我们得到一个数组:[[{name: 'Ron'}, {name: 'Alex'}]],这很难处理。所以我们想要创建一个新数组,我们将allContacts数组中的所有数组连接成一个数组。幸运的是,有一种方法可以调用在数组中接受参数的.concat方法。它看起来有点奇怪,但我们可以这样做:(更多关于.apply

const allContactsFlattened = 
   Array.prototype.concat.apply([], allContacts);

所以现在我们拥有了我们想要的东西:所有联系人的“平面”(一级)数组。您的过滤方法已经知道如何处理,因此不必进行进一步的更改。

要查看它的实际效果,我将您的代码包含在应用的更改中(以稍微不同的方式)+一些注释:

let originalContacts = [
	{"name":"Ron (parent)", "children":[{"name":"Alex (child)"}, {"name":"Emma (child)"}]},
  {"name":"Isa (parent)", "children":[{"name":"Sarah (child)"}, {"name":"Ahmad (child)"}]}
];

const Tab = ({ value }) => <div> {value} </div>;

class App extends React.Component {
  constructor() {
    super();
    this.state ={
      search: ''
    };
  }
  updateSearch(event){
    this.setState({search: event.target.value.substr(0,20)})
  }


  render() {
  	let contactsAndSubContacts = 
      // flatten the result
    	Array.prototype.concat.apply(
        // transform from parent =>  [parent, child1, child2 etc..]
      	[], originalContacts.map(contact => [contact, ...contact.children])
      );
    let filteredContacts = contactsAndSubContacts.filter((item)=>{
    	// NOTE: you probably want to use toLowerCase()
      // on this.state.search as well
      return item.name.toLowerCase().indexOf(this.state.search.toLowerCase())!==-1;
    });

    return(<div> 
        <h1> Contact List </h1>
        <input type="text" 
          value={this.state.search} 
          placeholder="Search Here" 
          onChange={this.updateSearch.bind(this)}  />
        <ul>
          {
            filteredContacts.map((obj, i) => 
                                 <Tab value={obj.name} key={i} />)
                                 }
        </ul>
      </div>
    );
  }
}
ReactDOM.render(<App/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>