如何在json数组中进行搜索,并在输入内容时返回结果

时间:2019-03-31 11:28:32

标签: javascript reactjs

到目前为止,仅当我键入api中存在的确切名称时,我才可以搜索数组的元素,在这种情况下,我的api具有一个包含20个位置的数组,如果我键入的是我搜索的元素的名称,则返回一个具有19个未定义位置和1个已找到位置的数组的数组,我想在键入时进行搜索,而不是仅在输入全名时进行搜索。 搜索之后,我尝试更改组件的状态,以便仅使用获取的值来呈现该组件,但是如果有人知道我非常感激,则不会发生这种情况。

updated code

 import data from "../sample_data/recipes.json";

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      searchString: []
    };
  }

  componentDidMount() {
    this.setState({ searchString: data.results })

  }

  onChange(fieldName) {
    if (fieldName === '' || fieldName === null) this.setState({ searchString: data.results });

    var indexes = data.results.filter((item, i) => {
      return item.title.toLowerCase().indexOf(fieldName.toLowerCase()) !== -1;    
    })  
    this.setState({ searchString : indexes });
  }

  render() {
    return (
      <div className="App">
        <Navbar onChange={this.onChange.bind(this)} />
        <div className="container mt-10">
          <div className="row">
            {<RecipeItem list={this.state.searchString} />}
          </div>
        </div>
      </div>
    );
  }
}

export default App;

4 个答案:

答案 0 :(得分:0)

  • setState移到map之外。
  • 使用for循环替换地图

也许试试看?

  var indexes = [];
  data.results.forEach(item => {
   if(item.title.indexOf(myObjTitle.title)) {
    indexes.push(item);
   }
  });
  this.setState({searchString : indexes});

答案 1 :(得分:0)

我不确定我是否完全理解您的问题,看来您正在尝试过滤匹配的结果。在这种情况下,最好使用filter而不是map

  onChange(fieldName) {
     if (fieldName === '' || !fieldName) {
       this.setState({ searchString: data.results })
     }

    const indexes = data.results.filter(item => (
      item.title === fieldName
    ));  
    this.setState({searchString : indexes});
  }

也就是说,如果您希望item.title和fieldName之间完全匹配。如果要查找包含搜索字符串fieldName的所有结果,则必须使用item.title.indexOf(fieldName) !== -1而不是item.title === fieldName。您可以在测试条件下更加微妙,例如为了不区分大小写。

另外,如果您想要单个结果(第一个匹配的结果),则使用find而不是filter更好,因为它会在第一个匹配之后停止搜索,而不是遍历整个数组

地图

返回一个新数组,其中的条目数量与以前一样多,但是您可以返回所需的任何内容作为条目,这就是为什么您现在获得这么多undefined条目的原因。 (因为仅当标题匹配时才返回一个项目,因此在不匹配时隐式返回undefined)。 Map遍历整个数组。

过滤器

返回一个新数组,其中包含与测试功能匹配的条目。如果函数返回true,则包含该项目,返回false,该项目将被省略。过滤器遍历整个数组。

查找

将仅检索与您的测试功能匹配的第一个条目。一旦找到匹配项,它将停止循环。

奖金

您最有可能需要学习有关反跳的知识,您可以使用lodash.debounce进行反跳。

去抖是一种用于防止函数在短时间内执行多次的方法(这样就不必渲染)

答案 2 :(得分:0)

我想您想在键入时进行某种过滤:

您可以试试吗? :

onChange(fieldName) {
    if (fieldName === '' || fieldName === null) this.setState({ searchString: data.results });

    var filteredItems = data.results.filter((item, i) => {
      return item.title.toLowerCase().indexOf(fieldName.toLowerCase()) === -1;    
    })  
    this.setState({ searchString : filteredItems });
  }

说明:

要求的是不显示包含键入字母的项目,为此,您可以将过滤器项目与filter方法一起使用,并仅返回标题中没有键入字母的项目(使用indexOf方法)。

答案 3 :(得分:0)

据我所知,您正在尝试从json Array中搜索元素,我刚刚添加了新键来存储filterString。这是我的解决方法

onChange(firstName){
 if(firstName != undefined){
   this.setState({
    nameToFilter : firstName
   })
 }
}

//在render方法内部 我正在使用nameToFilter来过滤数据。

render() {
    let searchString = this.state.searchString
    if(this.state.nameToFilter != undefined && this.state.nameToFilter.length>0)
    {
    searchString = this.state.searchString.filter(item => (
      item.title == this.state.nameToFilter
    ));
    }
    return (
      <div className="App">
        <Navbar onChange={this.onChange.bind(this)} />
        <div className="container mt-10">
          <div className="row">
            {<RecipeItem list={searchString} />}
          </div>
        </div>
      </div>
    );
  }