【问题标题】:Losing state between renders if component is defined in another component如果组件在另一个组件中定义,则在渲染之间丢失状态
【发布时间】:2021-06-08 18:37:47
【问题描述】:

此处的代码沙盒:https://codesandbox.io/s/restless-haze-v01wv?file=/src/App.js

我有一个用户组件(简化后)看起来像这样:

const Users = () => {
  const [toastOpen, setToastOpen] = useState(false)

  // functions to handle toast closing
  return (
   <EditUser />
   <Toast />
  )
}

const EditUser = () => {
  [user, setUser] = useState(null)
  useEffect(() => {
    const fetchedUser = await fetchUser()
    setUser(fetchedUser)
  }, [])

  // this approach results in UserForm's username resetting when the toast closes
  const Content = () => {
    if (user) return <UserForm user={user} />
    else return <div>Loading...</div>
  }
  return <Content />

  // if I do this instead, everything's fine
  return (
    <div>
    {
      user ? <UserForm user={user} /> : <div>Loading...</div>
    }
    </div>
  )
}

const UserForm = ({ user }) => {
  const [username, setUsername] = useState(user.name)

  return <input value={username}, onChange={e => setUsername(e.target.value)} />
}

在 Toast 仍处于打开状态时查看用户窗体页面时,用户窗体状态会在 Toast 关闭时重置。

我发现问题在于EditUser 内部定义的Content 组件,但我不太清楚为什么这是一个问题。我很想在这里了解一下 React 引擎盖下发生的事情,以及在“幸福的道路”中发生的事情

【问题讨论】:

标签: reactjs react-hooks closures use-state


【解决方案1】:

您在 EditUser 组件中定义了 Content ,而我们从来没有使用 React 组件,因为在这种情况下,Content 将在每次 EditUser重新创建 strong>重新渲染。 (当然,EditUser 将被重新渲染几次/多次)。

因此,重新创建的Content 组件意味着旧的Content 将被销毁(卸载),而新的Content 将被安装。

这就是为什么它被多次挂载,因此重置 状态值 为初始值。

因此,解决方案是在外部定义它(内容) - 不在任何其他反应组件内部

【讨论】:

  • 有道理,谢谢。所以当 React 去渲染 &lt;Content /&gt; 时,会发生这种情况:“我必须渲染一个 Content 组件。Content 功能与我上次渲染这个组件时不同,所以我必须卸载之前的 Content 组件并从头开始重新创建一个“?
  • 没错!这是正确的。当它渲染一个 new 组件时,它会从头开始设置新的状态,并且它会丢失所有以前的状态值。我没有尝试过,但我想,我们可以在组件内保留一个组件定义,并使用 useCallback 钩子来防止它重新创建 b>,但它会以复杂的方式做一件简单的事情,所以不推荐。
【解决方案2】:

罪魁祸首是 EditUser 的 Content 函数,每次调用它都会返回一个全新的实例。

【讨论】:

  • 是的。它不应该在组件内定义。
  • 您能解释一下原因吗?我觉得这与创建一个新的闭包有关(每次都会创建一个具有新状态的新组件),但我对细节真的很模糊。我很想快速了解在这个失败案例和“正确”案例中会发生什么。
猜你喜欢
  • 2020-10-21
  • 2019-10-14
  • 2020-05-27
  • 1970-01-01
  • 2021-02-16
  • 2021-12-04
  • 1970-01-01
  • 2023-04-06
  • 1970-01-01
相关资源
最近更新 更多