【问题标题】:unable to perform dynamic search in react app using static data无法使用静态数据在反应应用程序中执行动态搜索
【发布时间】:2018-08-30 05:33:57
【问题描述】:

我正在我的 react 应用程序上执行排序、过滤和分页,该应用程序显示来自包含电影数据的 json 文件中的数据。我能够从输入框中获取数据,但无法 setState 以及控制台日志 searchKey 和电影。

下面是 App.js 和 Hello.js 的代码。 App 组件同时具有排序和搜索功能。

App.js

import data from './data.json';

class App extends Component {
  constructor() {
    super();
    this.state = {
      movies: data.movies, sort_term: '', searchKey: '', filterList: '',
    };
    this.onSorting = this.onSorting.bind(this);
    this.onSearchMovie = this.onSearchMovie.bind(this);
  }
  onSorting = (e) => {
    let term = 'Title';
    let option = e.target.value;
    let sortedList = [...this.state.movies].sort((a, b) => {
      return (option == 'asc' ? (a[term] <= b[term] ? -1 : 1) :
        (a[term] >= b[term] ? -1 : 1))
    });
    this.setState({ sort_term: term });
    this.setState({ movies: sortedList });
  }
  onSearchMovie(e) {
    let key = e;
     console.log(key);
     this.setState({searchKey : key });
     console.log(searchKey);
     let list = movies.filter(m =>{
       return m.Title.toLowerCase().includes(searchKey.toLowerCase());
     });
     this.setState({movies:list});
  }
  render() {
    const { movies } = this.state;

    if (!movies.length) {
      return (
        <div className="container">
          <h2>loading...</h2>
        </div>
      );
    }
    else {
      return (
        <div>
          <Hello sort_term={this.state.sort_term}
            onSorting={this.onSorting}
            onSearch={this.onSearchMovie} />
          <br />
          <Table movies={this.state.movies} />
        </div>
      );
    }
  }
}

你好.js

class Hello extends Component {
  constructor(props) {
    super(props);
    this.state = { inputField: '', }
    this.onSubmitTitle = this.onSubmitTitle.bind(this);
    this.getTitle = this.getTitle.bind(this);
  }
  onSubmitTitle(e){
    e.preventDefault();
    this.props.onSearch(this.state.inputField);
    this.setState({ inputField: '' });
  }
  getTitle(e){
    this.setState({ inputField: e.target.value });
    // console.log('---');
  // console.log(this.state.inputField);
  }

  render() {
    const { sort_term, onSorting } = this.props;

    return (
      <div className="header">
        Database
        <ul className="navLeft">
          <li>
            <form onSubmit={this.onSubmitTitle}>
              <input type="search"  onChange={this.getTitle} value={this.state.inputField}
                className="search-bar"
                placeholder="Type for search..." />
            </form>
          </li>
          <li >
            <form >
              <select
                onChange={onSorting}
                className="searchBar">
                <option value="desc" >Sort Title(Z - A)</option>
                <option value="asc">Sort Title(A - Z)</option>
                 <option value="descDirector">Sort Director(Z - A)</option>
                <option value="ascDirector">Sort Director(A - Z)</option>
              </select>
            </form>
          </li>
        </ul>
      </div>
    );
  }
}

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    你有几个问题:

    • 这里有一些未定义的变量:

              onSearchMovie(e) {
                  let key = e;
                  console.log(key);
                  this.setState({ searchKey: key });
                  console.log(searchKey);
                  let list = movies.filter(m => {
                    return m.Title.toLowerCase().includes(searchKey.toLowerCase());
                  });
                  this.setState({ movies: list });
                }
      
       like `searchKey` and `movies`.
      
    • setState 是异步的,所以这样做:

              this.setState({ sort_term: term });
              this.setState({ movies: sortedList });
      
              Is the same as doing this:  
      
      
              this.setState({
                sort_term: term,
                movies: sortedList
              });
      
    • 话虽如此,这个代码块可能无法按预期工作:

          onSearchMovie(e) {
            let key = e;
            console.log(key);
            this.setState({ searchKey: key });
            console.log(searchKey);
            let list = movies.filter(m => {
              return m.Title.toLowerCase().includes(searchKey.toLowerCase());
            });
            this.setState({ movies: list });
          } 
      

      因为如上所述,setState 是异步的。所以this.state.searchKey 可能不是您在下一行访问它时的想法。
      要么使用key 变量,要么使用setState 回调,这将在setState 完成后触发。

      this.setState({someKey: someValue}, () =&gt; {console.log(this.state.someKey)})

      您可以在文档Why is setState giving me the wrong value? 中了解更多信息。

    • 您可能不知道的另一件事是,当您在form 上使用onSubmit 时,您实际上需要触发提交。既然你没有 任何提交按钮,您都可以使用enter 键来完成。所以当你
      专注于inputenter 键和form 将 提交。

    • 我要做的另一件事是显示和更新filteredMovis 直接列出而不是movies 列表,因为一旦您过滤 出项目,然后你不能让他们回来。所以当你过滤你 在movies 上执行此操作,但不更新filteredMovis 列表 从原始 movies 列表中删除项目。

    这是一个有效且正在运行的示例:

    const data = {
      movies: [
        {
          id: 1,
          Title: "wonder woman"
        },
        {
          id: 2,
          Title: "kill bill"
        },
        {
          id: 3,
          Title: "world war z"
        },
        {
          id: 4,
          Title: "pixels"
        }
      ]
    };
    
    class Hello extends React.Component {
      constructor(props) {
        super(props);
        this.state = { inputField: "" };
        this.onSubmitTitle = this.onSubmitTitle.bind(this);
        this.getTitle = this.getTitle.bind(this);
      }
      onSubmitTitle(e) {
        e.preventDefault();
        this.props.onSearch(this.state.inputField);
        this.setState({ inputField: "" });
      }
      getTitle(e) {
        this.setState({ inputField: e.target.value });
        // console.log('---');
        // console.log(this.state.inputField);
      }
    
      render() {
        const { onSorting } = this.props;
    
        return (
          <div className="header">
            Database
            <ul className="navLeft">
              <li>
                <form onSubmit={this.onSubmitTitle}>
                  <input
                    type="text"
                    onChange={this.getTitle}
                    value={this.state.inputField}
                    className="search-bar"
                    placeholder="Type for search..."
                  />
                </form>
              </li>
              <li>
                <form>
                  <select onChange={onSorting} className="searchBar">
                    <option value="desc">Sort Title(Z - A)</option>
                    <option value="asc">Sort Title(A - Z)</option>
                    <option value="descDirector">Sort Director(Z - A)</option>
                    <option value="ascDirector">Sort Director(A - Z)</option>
                  </select>
                </form>
              </li>
            </ul>
          </div>
        );
      }
    }
    
    class App extends React.Component {
      constructor() {
        super();
        this.state = {
          movies: data.movies,
          filteredMovis: data.movies,
          sort_term: "",
          searchKey: "",
          filterList: ""
        };
        this.onSorting = this.onSorting.bind(this);
        this.onSearchMovie = this.onSearchMovie.bind(this);
      }
      onSorting = e => {
        let term = "Title";
        let option = e.target.value;
        let sortedList = [...this.state.movies].sort((a, b) => {
          return option == "asc"
            ? a[term] <= b[term]
              ? -1
              : 1
            : a[term] >= b[term]
              ? -1
              : 1;
        });
        this.setState({
          sort_term: term,
          filteredMovis: sortedList
        });
      };
      onSearchMovie(key) {
        const { movies } = this.state;
        let list = movies.filter(m => {
          return m.Title.toLowerCase().includes(key.toLowerCase());
        });
        this.setState({ filteredMovis: list, searchKey: key });
      }
      render() {
        const { filteredMovis, movies } = this.state;
    
        if (!movies.length) {
          return (
            <div className="container">
              <h2>loading...</h2>
            </div>
          );
        } else {
          return (
            <div>
              <Hello
                sort_term={this.state.sort_term}
                onSorting={this.onSorting}
                onSearch={this.onSearchMovie}
              />
              <br />
              {filteredMovis.map(movie => <div key={movie.id}>{movie.Title}</div>)}
            </div>
          );
        }
      }
    }
    
    const rootElement = document.getElementById("root");
    ReactDOM.render(<App />, rootElement);
    <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>

    【讨论】:

    • let list = movies.filter(m => { return m.Title.toLowerCase().includes(key.toLowerCase()); });
    • 我要获取的电影没有定义,但我已经设置了电影
    • 但是你需要通过状态对象来访问它。 this.state.movies
    • 目前我可以搜索,但无法显示多个数据
    • 例如,如果我有世界大战、神奇女侠、世界大战 z,那么它不会显示搜索结果,直到我输入唯一的单词
    猜你喜欢
    • 1970-01-01
    • 2020-12-19
    • 1970-01-01
    • 1970-01-01
    • 2020-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多