【问题标题】:UI does not render after state is changed状态更改后 UI 不呈现
【发布时间】:2018-03-14 09:04:51
【问题描述】:

我在React 有一个应用程序(Udacity 中的项目),它根据以下类别在我的书架上显示书籍:正在阅读想阅读阅读。每次我将类别从想要阅读更改为当前阅读时,这本书都会移动到正确的类别,在这种情况下它将是当前阅读。我的代码适用于这个没有问题。但是,您也可以从可以移动到书架的庞大图书库中进行搜索,默认情况下类别为“无”,尽管您可以将书架中的现有图书作为搜索的一部分(除了主图书馆的图书)。现在,我的问题是,如果我从 None 移动到 Want To Read 类别,例如,我的 UI 在单击返回按钮后不会改变主页(即 App.js)。但是,当我这样做时,主要是更改类别,我没有问题。此外,我在 App.js 中更新书架的功能在调用时不会在控制台中显示任何错误。

我有以下组件:

 App
  |
  |--BooksSearch
  |--BooksList
  |     |--BookShelf
  |--BooksSearchPage
        |--BookShelf

BooksListBooksSearch 分别在主页(即 App.js)中显示书籍和搜索按钮。 BooksSearchPage 允许用户从图书馆搜索书籍以移入书架。 BookShelf 显示书籍列表,无论它们是在书架上还是在图书馆里。

这是我的 App.js

class App extends React.Component {

 state = {
 mybooks : [], 
 showSearchPage: false
}

componentDidMount() { 
 BooksAPI.getAll().then( (mybooks)=> { 
    this.setState({mybooks})
 })}

toCamelShelf(Shelf) {
 if (Shelf==="currentlyreading") return "currentlyReading"
 if (Shelf==="wanttoread") return "wantToRead"
 return Shelf
}

updateBookShelf = (mybook, shelf) => {
shelf=this.toCamelShelf(shelf)
BooksAPI.update(mybook, shelf).then(
this.setState((state)=>({      
    mybooks: state.mybooks.map((bk)=>bk.id === mybook.id ? 
    {...bk, shelf:shelf} : bk)
 })))}

render() {
 return (
   <div className="app">
     {this.state.showSearchPage ? (
       <Route path='/search' render={({history})=>(
        <BooksSearchPage mybooks={this.state.mybooks} onSetSearchPage={
            ()=>{ this.setState({showSearchPage:false});
                  history.push("/");
              }}
              onUpdateBookShelf={this.updateBookShelf}
            />
      )} />
    ) : (
      <Route exact path='/' render={()=>(
        <div className="list-books">
          <div className="list-books-title">
            <h1>My Reads</h1>
          </div>
          <BooksList mybooks={this.state.mybooks} 
            onUpdateBookShelf={this.updateBookShelf}/>
          <BooksSearch onSetSearchPage={()=>this.setState({showSearchPage:true})}/>
        </div>
      )} />           
    )}
  </div>
  )
 }
}

export default App

由于代码太长,我在 Github 中包含了我的 repo。我是 ReactJS 的新手,过去 3 天一直在调试这个问题,但无济于事。

【问题讨论】:

    标签: javascript reactjs ecmascript-6 react-router


    【解决方案1】:

    我很难完全理解该应用程序以确切知道原因,但这听起来像是一个状态问题。

    如果您导航离开并返回,或者单击某些内容但它没有正确更新,则状态在那个时刻(那个事件)没有更新,或者在那个事件之前没有正确保存状态。

    一旦您重现问题事件,就问自己“我这样做之前的状态是什么?”以及“为什么现在是这样的状态?”

    1. 您忘记更新状态了吗?
    2. 它是否从某个地方获得了错误的状态?
    3. 你打电话给this.setState({ something })了吗?
    4. 您是否覆盖了状态而不是添加状态?
    5. 是否缺少状态更新?

    在两个页面的前后,添加渲染方法:console.log(this.state),如果需要,添加console.log(this.props)。我想如果你看那里,你会发现问题。问题是它到底是怎么变成这样的?重新访问您的所有状态更新。

    如果您离开并返回,它从哪里获得该状态?为什么会有这些数据?

    记住,React 是一个状态机。状态是一个对象,每次查看它时都有数据快照。这就像看一张纸,上面有你所有的数据。如果你离开房间然后回来但数据不存在,是什么更新了你的状态并让它消失了?或者为什么它没有被添加到你的状态?那里的机制导致了您的问题。

    我在您的代码中看到了一些需要关注的地方:

    BooksAPI.update(mybook, shelf).then(
    this.setState((state)=>({      
        mybooks: state.mybooks.map((bk)=>bk.id === mybook.id ? 
        {...bk, shelf:shelf} : bk)
     })))}
    

    <BooksSearchPage mybooks={this.state.mybooks} onSetSearchPage={
            ()=>{ this.setState({showSearchPage:false});
                  history.push("/");
              }}
              onUpdateBookShelf={this.updateBookShelf}
    

    <BooksList mybooks={this.state.mybooks} 
                onUpdateBookShelf={this.updateBookShelf}/>
              <BooksSearch onSetSearchPage={()=>this.setState({showSearchPage:true})}/>
    

    也在这里:

    class App extends React.Component {
      state = {
      mybooks : [], 
      showSearchPage: false
     }
    
    componentDidMount() { 
     BooksAPI.getAll().then( (mybooks)=> { 
        this.setState({mybooks})
     })}
    

    我怀疑其中一个行为过于强烈,或者其中一个没有在正确的时间更新,或者数据被覆盖。

    console.log() 应该是最有帮助的。如果您的数据丢失。让它在那个时候出现,问题就会消失 :)(P.S. componentDidMount 上的 setState 看起来有点可疑)。

    【讨论】:

    • 首先感谢您的回复。我做了很多console.log,尤其是App.js 中的updateBookShelf。我一定会尝试做更多console.log,正如您从州到州或逐页建议的那样(可能是虚拟的)。我不相信它是ComponentDidMount,因为它到目前为止运行良好,尽管我可能弄错了。
    • 你提到了一些关于添加书架上的书,所以听起来需要进行某种合并,而且听起来肯定会回归到不正确或旧的状态。
    • 在上面撒一点console.log,这样你就可以说“嗯,这不正确”,然后查看状态……然后检查之前的事件。我强烈地觉得你可以找到它在拖你的地方。也许甚至组件都没有重新渲染,这导致状态不更新(因为你说你正在导航)。我还建议在进入设置状态时使用 console.logging 一切正在播放的内容。看看有没有异常。如果必须的话,就像从字面上记录所有内容一样。在想象数据必须如何流动的同时积极进行取证。
    • 感谢您的建议,非常感谢。
    • 干得好。如果您还记得我的任何事情,请将其设为史诗般的 console.log 垃圾邮件,以便您可以查看 3 个关键角度:before / now / after,就像一个弹跳的球。以下是图片形式的 3 个角度:\ _ /。这只是一个不可变、无状态世界中的事件和状态。
    猜你喜欢
    • 2020-08-07
    • 2019-04-10
    • 1970-01-01
    • 2021-01-24
    • 1970-01-01
    • 2019-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多