这是父组件:

    state = {
    books: undefined
  }

  componentDidMount() {
    BooksAPI.getAll().then(books => {
      this.setState({books},this.filterBooks);
    });
  }

  filterBooks() {
    this.currentlyReading = this.state.books.filter((book) => book.shelf === 'currentlyReading');
    this.read = this.state.filter((book) => book.shelf === 'read');
    this.wantToRead = this.state.filter((book) => book.shelf === 'wantToRead');
  }

  render() {
    return (
      <div className="app">
        <Route path="/search" component={SearchBook} />
        <Route exact
          path="/"
          render={() => <BookScreen
            currentlyReading={this.currentlyReading}
            read={this.read}
            wantToRead={this.wantToRead}
          />} />
      </div>
    )
  }


我希望在调用filterBooks之后,BookScreen组件的道具会更改,并且该组件应该重新呈现,但事实并非如此。我究竟做错了什么?

最佳答案

在我看来,目前最好的方法(仍然遵循React的方法)是:在拥有books数据之后,仅调用1函数,该函数将处理所有内容并在完成后更新状态(我们将books对象作为参数传递), 像这样:

  componentDidMount() {
    BooksAPI.getAll().then(books => {
      this.filterBooks({books});
    });
  }

  filterBooks = (books) => {
    this.currentlyReading = books.filter((book) => book.shelf === 'currentlyReading');
    this.read = books.filter((book) => book.shelf === 'read');
    this.wantToRead = books.filter((book) => book.shelf === 'wantToRead');
    this.setState({ books: books });
  }


如果您有任何错误,请随时在此处发布,我们可以一起解决!

========

添加了有关作者原始代码为何无效的说明:

根据我对React和JS的一点经验:

设置新状态后,可能要花费一些时间(可能是100-300ms,这就是为什么使用语法this.filterBooks执行原始this.setState({books},this.filterBooks)的原因

=>这似乎是正确的,这意味着在已经设置books的新状态之后,您可以使用filterBooks函数访问它。)

但是:设置books的新状态后,将重新呈现页面,并执行filterBooks(也许在同一时间=>不确定哪个先结束,所以举个例子,例如this.currentlyReading的结果之前先出现render(),则在render()中仍未定义>!

换句话说,React是Javascript,而Javascript的异步性很麻烦!

10-06 06:49