如果组件在另一个组件中定义,则在渲染之间丢失状态
Losing state between renders if component is defined in another component
codesandbox 在这里: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 引擎盖下发生的事情,以及在“快乐之路”中发生的事情
您已经在 EditUser
组件中定义了 Content
,而我们在 React Components 中从未这样做过,因为在这种情况下,Content
将被 重新创建 每次 EditUser
被 重新渲染 。 (当然,EditUser 将被重新渲染 few/many 次)。
因此,重新创建的 Content
组件意味着旧的 Content
将被销毁(卸载)并安装新的 Content
。
这就是为什么它被多次安装,因此 重置 状态值 到初始值。
因此,解决方案是在外部定义它(内容)- 而不是在任何其他 React 组件内部。
罪魁祸首是 EditUser 的 Content
函数,可以预见,每次调用它时 returns 都是一个全新的实例。
codesandbox 在这里: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 引擎盖下发生的事情,以及在“快乐之路”中发生的事情
您已经在 EditUser
组件中定义了 Content
,而我们在 React Components 中从未这样做过,因为在这种情况下,Content
将被 重新创建 每次 EditUser
被 重新渲染 。 (当然,EditUser 将被重新渲染 few/many 次)。
因此,重新创建的 Content
组件意味着旧的 Content
将被销毁(卸载)并安装新的 Content
。
这就是为什么它被多次安装,因此 重置 状态值 到初始值。
因此,解决方案是在外部定义它(内容)- 而不是在任何其他 React 组件内部。
罪魁祸首是 EditUser 的 Content
函数,可以预见,每次调用它时 returns 都是一个全新的实例。