Reactjs 如果组件在另一个组件中定义,则在渲染之间丢失状态

Reactjs 如果组件在另一个组件中定义,则在渲染之间丢失状态,reactjs,react-hooks,closures,use-state,Reactjs,React Hooks,Closures,Use State,代码沙盒: 我有一个用户组件(简化后)如下所示: const Users = () => { const [toastOpen, setToastOpen] = useState(false) // functions to handle toast closing return ( <EditUser /> <Toast /> ) } const EditUser = () => { [user, setUser] = u

代码沙盒:

我有一个用户组件(简化后)如下所示:

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)} />
}

const Users=()=>{
const[toastOpen,setToastOpen]=useState(false)
//处理toast关闭的函数
返回(
)
}
常量EditUser=()=>{
[user,setUser]=useState(null)
useffect(()=>{
const fetchedUser=await fetchUser()
setUser(fetchedUser)
}, [])
//这种方法会在toast关闭时重置UserForm的用户名
常量内容=()=>{
如果(用户)返回
否则返回加载。。。
}
返回
//如果我这样做,一切都好
返回(
{
用户?:正在加载。。。
}
)
}
常量UserForm=({user})=>{
const[username,setUsername]=useState(user.name)
返回setUsername(e.target.value)}/>
}
在Toast仍处于打开状态时查看UserForm页面时,当Toast关闭时,UserForm状态将重置


我发现问题在于
EditUser
中定义的
Content
组件,但我不太清楚这是一个问题的原因。我想了解一下React引擎盖下发生的事情,以及“快乐之路”中发生的事情。您已经在React组件中定义了
Content
,我们从未使用过React组件,因为在这种情况下,
内容
将在每次
编辑用户
重新呈现时被重新创建。(当然,EditUser将被重新渲染几次/多次)

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

这就是为什么要多次安装它,从而将状态值重置为初始值


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

罪魁祸首是EditUser的
内容
函数,它可以预测每次调用时都会返回一个全新的实例。

您可以共享用户的完整代码吗componentRelated:是的。它不应该在组件内部定义。你能解释一下为什么吗?我有一种感觉,它与创建一个新的闭包(每次都会创建一个具有新状态的新组件)有关,但我对细节非常模糊。我想快速了解一下在这个失败案例和“正确”案例中会发生什么。很有意义,谢谢。因此,当React转到render
时,是否会发生这样的情况:“我必须呈现一个内容组件。内容函数与上次呈现此组件时不同,因此我必须卸载以前的内容组件并从头开始重新创建一个”?完全正确!没错。当它呈现一个新的组件时,它会从头开始设置新的状态,并且会丢失所有以前的状态值。我还没有尝试过,但我想,我们可以在组件中保留一个组件定义,并使用useCallback钩子来防止它被重新创建,但这将以复杂的方式完成一件简单的事情,因此不推荐使用。