【问题标题】:React JS: Two Filters on the same JSON dataReact JS:相同 JSON 数据的两个过滤器
【发布时间】:2021-06-19 09:55:38
【问题描述】:

问题总结 我有两个输入要过滤数据:

  1. 过滤 videoTitle 和 teacherName
  2. 标签过滤(JSON 中的嵌套数组)

我无法让tag 过滤器工作。它目前似乎根本没有过滤 JSON,只是返回所有数据。

上下文 目前已在第一个过滤器(videoTitle 和教师姓名)上成功提取和过滤数据。

环境:MacOS 11.2.3、React 17.0.1、VSCode

我尝试了什么? 获得条件的可见性以查看返回的内容。似乎条件是通过标签数组过滤,但返回不起作用。

代码

获取数据和映射

import React, { Component } from 'react';
import axios from 'axios';

class Search extends Component {
  state = {
    error: false,
    searchQuery: "",
    tagQuery: "",
    results: [],
    loadingData: false,
  }

  getInfo = () => {
    this.setState({ loadingData: true })
    axios.get('https://**********')
    .then(({ data }) => {
      data.sort((a, b) => b.averageUserRating - a.averageUserRating);
        this.setState({ results: data });
        this.setState({ loadingData: false })
    })
    .catch(() => this.setState({ error: true }))
  }

2x 更改处理程序(每个输入一个)

  handleSearchInputChange = () => {
    this.setState({
      searchQuery: this.search.value
    }, () => {
      if (this.state.searchQuery && this.state.searchQuery.length > 1) {
        if (this.state.searchQuery.length % 2 === 0) {
          this.getInfo()
        }
      } else if (this.state.searchQuery === "") {
          this.setState({ results: [] })
      }
    })
  }

  handleTagInputChange = () => {
    this.setState({
      tagQuery: this.tag.value
    }, () => {
      if (this.state.tagQuery && this.state.tagQuery.length > 1) {
        if (this.state.tagQuery.length % 2 === 0) {
          this.getInfo()
        }
      } else if (this.state.tagQuery === "") {
          this.setState({ results: [] })
      }
    })
  }

渲染方法

render() {

    const searchForTutorials = this.state.results.filter((data) => {
      if (this.state.searchQuery == null)
        return data;
      else if (data.videoTitle.toLowerCase().includes(this.state.searchQuery.toLowerCase()) || data.teacherName.toLowerCase().includes(this.state.searchQuery.toLowerCase())) {
        return data;
      }
    }).map(data => {
      return (
        <div>
          <ul>
            <li style={{position:'relative', left: '10vh'}}>
              <span style={{paddingRight:'10px'}}>{data.videoTitle}</span>
              <span style={{paddingRight:'10px'}}>{data.videoUrl}</span>
              <span style={{paddingRight:'10px'}}>{data.teacherName}</span>
              <span style={{paddingRight:'10px'}}>{data.tags.map(word => word)}</span>
              {/* <span style={{paddingRight:'10px'}}>{data.averageUserRating}</span> */}
            </li>
          </ul>
        </div>
      )
    })

    const searchForTags = this.state.results.filter((data) => {
      if (this.state.tagQuery == null)
        return data;
      else if (data.tags.map(word => word.toLowerCase()).includes(this.state.tagQuery.toLowerCase())) {
        return data;
      }
    }).map(data => {
      return (
        <div>
          <ul>
            <li style={{position:'relative', left: '10vh'}}>
              <span style={{paddingRight:'10px'}}>{data.videoTitle}</span>
              <span style={{paddingRight:'10px'}}>{data.videoUrl}</span>
              <span style={{paddingRight:'10px'}}>{data.teacherName}</span>
              <span style={{paddingRight:'10px'}}>{data.tags.map(word => word)}</span>
              {/* <span style={{paddingRight:'10px'}}>{data.averageUserRating}</span> */}
            </li>
          </ul>
        </div>
      )
    })

    return (
      <form>
        <input
          type="text"
          placeholder="Search for Tutorials..."
          ref={input => this.search = input}
          onChange={this.handleSearchInputChange}
          />

          <input
            type="text"
            placeholder="Search using Tags..."
            ref={input => this.tag = input}
            onChange={this.handleTagInputChange}
          />

          {this.state.loadingData && <button>Loading...</button>}
          {!this.state.loadingData &&
          <button 
            type="button" 
            onClick={() => this.getInfo() }>
            <span>Refresh Data</span>
      </button>}
          {searchForTutorials}
          {searchForTags}
      </form>

    )
  }
}

export default Search;

【问题讨论】:

  • 与问题本身无关的细节太多。如果您删除不必要的细节,它会更容易为您提供帮助。
  • 您的过滤结果条件不好用:'' == null // false。在你的代码中它永远不会是真的,那么,你为什么要把它放在那里?
  • 另外,您将结果内容呈现两次,这看起来不正确。要修复它,您需要链接过滤器调用并渲染一次结果。
  • 我对 React 比较陌生,不确定如何为两个不同的输入呈现数据,所以这是我的工作,直到我弄明白为止。感谢您提供有关链接过滤器调用的提示。

标签: javascript json reactjs filter


【解决方案1】:

searchForTags过滤方法中,第二个if:

else if (data.tags.map(word => word.toLowerCase()).includes(this.state.tagQuery.toLowerCase())) {

我不确定你是否打算在这里,但你正在返回一个布尔值数组 [true, false, true, ...] 值,它总是评估为真。您应该在映射值上使用 run some function 以查找是否有任何相关标签

例如:

const searchForTags = this.state.results.filter((data) => {
  if (this.state.tagQuery === null) {
    return true;
  }
  return data.tags
    .map(word => word.toLowerCase())
    .some(word => word === this.state.tagQuery.toLowerCase()); // stops at the first match found and return true
}

请记住,当您使用 Array.filter 时,您的函数应该返回一个布尔值,以便保留它或从过滤中丢弃。

【讨论】:

  • 托梅,谢谢。这很有意义。我现在就试试看。
  • 看起来我的返回函数正在为所有内容返回true(即使使用 Tomeu 的代码)。这意味着在tagQuery 输入中输入的任何内容都会返回所有数据。
  • 作为此类问题的一般建议,我建议检查返回过滤功能的内容。检查是否使用已知值手动硬编码tagQuery 并从那里开始
  • @timcastillogill,可能所有数据都是从searchForTutorials 渲染的,
  • searchForTutorials 根据videoTitleteacherName 返回过滤表,这就是为什么我认为这是我通过标签映射过滤的方式。
猜你喜欢
  • 2023-03-26
  • 1970-01-01
  • 2019-09-09
  • 1970-01-01
  • 1970-01-01
  • 2018-12-30
  • 1970-01-01
  • 2020-09-28
  • 2020-08-07
相关资源
最近更新 更多