【问题标题】:React hooks - useState() is not re-rendering the UI with the new state updatesReact hooks - useState() 不会使用新的状态更新重新渲染 UI
【发布时间】:2019-06-26 23:14:26
【问题描述】:

我正在尝试新的 React Hooks,但我有点卡住了,因为当本地状态更新时 UI 没有更新。这是我的代码,

import React, { useState, useEffect } from 'react';
import Post from './Post'
import PostForm from './PostForm';
import axios from 'axios';

function PostsList() {
  const [posts, setPosts] = useState([]);
  
  // setting up the local state using useEffect as an alternative to CDM
  useEffect(() => {
    axios.get('...')
      .then(res => {
        // the resposne is an array of objects
        setPosts(res.data)
      })
  })
  
  const handleSubmit = (data) => {
    // the data I am getting here is an object with an identical format to the objects in the posts array
    axios.post('...', data)
      .then(res => {
        // logging the data to validate its format. works fine so far..
        console.log(res.data);
        // the issue is down here
        setPosts([
          ...posts,
          res.data
        ])
      })
      .catch(err => console.log(err))
  }
  
  return (
    <div>
      <PostForm handleSubmit={handleSubmit}  />
      <h3>current posts</h3>
      
      { posts.map(post => (
        <Post key={post.id} post={post} />
      )) }
    </div>
  )
}

当我提交表单时,UI 会闪烁片刻,然后在没有新更新的情况下呈现当前状态,似乎有什么东西阻止了它重新呈现新状态。 如果需要更多代码/说明,请在下面发表评论。 提前致谢。

【问题讨论】:

  • 实际上,由于您没有将第二个参数传递给useEffect,因此它充当 cDM + cDU,因此在每次渲染时都会调用它。假设它是关于添加新的和从服务器实际列表加载之间的竞争条件。您确定第二次点击提交之前添加的帖子没有与其他帖子一起加载吗?
  • 实际上这很有意义,所以我猜它在提交表单后闪烁的原因是它被handleSubmit()更新的时间,并且由于useEffect()重新渲染了dom,所以它渲染来自服务器的旧帖子..所以现在的问题是如何防止这种情况发生,换句话说,如何像我们以前使用cDM() 那样设置本地状态并防止cDU() 在状态时运行更新了吗?
  • 好吧,我明白了,我只是在传递给useEffect()的回调函数的结束标记之后添加了一个空数组,这使得组件只渲染一次,而不是每次状态获取更新。谢谢人:)
  • np。您可以通过突出显示这件事来创建简短的答案/接受它吗?找到这个问题的人会更清楚

标签: javascript reactjs react-hooks


【解决方案1】:

好的,@skyboyer 的有用提示解决了问题,
所以最初发生的事情是,useEffect() 同时表现得像componentDidMount()componentDidUpdate(),这意味着只要状态有更新,useEffect() 就会被调用,这意味着用初始状态重置状态来自服务器的数据。 为了解决这个问题,我需要让 useEffect() 在创建/渲染组件时只渲染一次,而不是在每次状态更新时渲染它。这是通过向useEffect() 函数添加一个空数组作为第二个参数来完成的。如下图。

 useEffect(() => {
   axios.get('...')
    .then(res => {
      setPosts(res.data)
     })
   }, [])
谢谢 :)

【讨论】:

    猜你喜欢
    • 2020-05-12
    • 1970-01-01
    • 2021-09-09
    • 2019-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-05
    相关资源
    最近更新 更多