无法使用静态数据在react app中执行动态搜索

问题描述 投票:1回答:1

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

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

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

Hello.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个回答
2
投票

你有几个问题:

  • 你在这里得到了一些未定义的变量: 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}, () => {console.log(this.state.someKey)}) 您可以在文档Why is setState giving me the wrong value?中阅读更多相关信息。
  • 你可能不知道的另一件事是当你使用onSubmitform你实际上需要触发提交。由于您没有任何提交按钮,您可以使用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>
© www.soinside.com 2019 - 2024. All rights reserved.