将setState与onChange一起使用不会更新

时间:2018-03-13 21:20:10

标签: javascript reactjs input onchange setstate

我在寻找什么?setState()元素上使用input的方法,可以使用state立即更新onChange

到目前为止我做了什么?

我有两个组件BooksAppSearchBook。我将result传递给SearchBook作为要渲染的道具。然后,我使用input捕获onChange元素上的更改。 onChange正在调用我作为道具传递的方法。 React documentation说明如下,但是如果我使用回调然后在回调中调用setState(),那么我觉得我回到了同样的情况,因为setState()将再次出现异步:

  

setState()并不总是立即更新组件。它可以批量推迟更新或推迟更新。这使得在调用setState()之后立即读取this.state是一个潜在的陷阱。相反,使用componentDidUpdate或setState回调(setState(更新程序,回调)),其中任何一个都保证在应用更新后触发。如果需要根据以前的状态设置状态,请阅读下面的updater参数。

有什么问题? 如果用户过快地删除input的内容,虽然控制台中仍有console.log('empty'),但setState()不会运行,因此result保持不变,不会成为一个空数组。

这是App.js

的内容
class BooksApp extends Component {
  state = {
    books: [],
    result: [],
    query: ''
  }
  updateQuery = (query) => {
    this.setState({ query: query.trim() })
  }
  objDigger = (arr, diggers) => {
    const digged = [];
    diggers.forEach((d) => {
      let o = {};
      o = arr.filter((a) => a.id === d);
      o.forEach((i) => {
        digged.push(i);
      })
    });
    return digged;
  }
  filterHelper = (result) => {
    const resultKeys = result.map((r) => r.id)
    const stateKeys = this.state.books.map((s) => s.id)
    // this.objDigger(this.state.books, stateKeys)

    // new books
    const newKeys = _array.difference(resultKeys, stateKeys);
    const newObjs = this.objDigger(result, newKeys)

    // existing books
    const existingKeys = _array.difference(resultKeys, newKeys)
    const existingObjs = this.objDigger(this.state.books, existingKeys);

    // search books
    const searchObjs = newObjs.concat(existingObjs);
    return searchObjs;
  }
  searchBook = (query) => {
    this.updateQuery(query);
    if (query) {
      BooksAPI.search(query).then((result) => {
        result = this.filterHelper(result)
        if (!result.error) {
          this.setState({
            result,
          })
        }
      })
    } else {
      console.log('empty');
      this.setState(state => ({
        result: []
      }));
    }
  }
  appHandleChange = (query) => {
    console.log('searching');
    this.searchBook(query);
  }
  render() {
    return (
      <div className="app">
        <Route path="/search" render={() => (
          <SearchBook
            result={ this.state.result }
            onChange={ this.appHandleChange }
            onChangeShelf={ this.changeShelf }/>
        )}>
        </Route>
      </div>
    )
  }
}

这是SearchBook

的内容
class SearchBook extends Component {
  handleChange = (book, newShelf) => {
    this.props.onChangeShelf(book, newShelf);
  }
  handleInputChange = (event) => {
    this.props.onChange(event.target.value);
  }
  render() {
    const { result } = this.props;

    return (
      <div className="search-books">
        <div className="search-books-bar">
          <Link
            to="/"
            className="close-search"
          >
            Close
          </Link>
          <div className="search-books-input-wrapper">
            <input
              type="text"
              placeholder="Search by title or author"
              onChange={ (event) => this.handleInputChange(event) }
            />

          </div>
        </div>

        <div className="search-books-results">
          <ol className="books-grid">
            {result.length>0 && result.map((book) => (
              <li key={book.id}>
                <div className="book">
                  <div className="book-top">
                    <div className="book-cover" style={{ width: 128, height: 193, backgroundImage: `url(${book.imageLinks && book.imageLinks.smallThumbnail})` }}></div>
                    <BookShelfChanger
                      shelf={book.shelf ? book.shelf : 'none'}
                      onChangeShelf={(newShelf) => {
                        this.handleChange(book, newShelf)
                      }}
                    ></BookShelfChanger>
                  </div>
                  <div className="book-title">{book.title}</div>
                  <div className="book-authors">{book.authors}</div>
                </div>
              </li>
            ))}
          </ol>
        </div>
      </div>
    )
  }
}

0 个答案:

没有答案