[英]Is initial state based on props always bad in React?
React 的一个常见知识是,如果我们不使它们同步,则由 props 初始化 state 是不好的。 这被认为很好:
import { useState, useEffect } from 'react';
export default function MyInput({ initialValue }) {
const [value, setValue] = useState(initialValue);
useEffect(
() => setValue(initialValue),
[initialValue]
);
return (
<>
<h1>The value is {value}</h1>
<input
type="text"
value={value}
onChange={event => setValue(event.target.value)}
/>
</>
);
}
但是,如果我实际上不想在initialValue
更改时更新值并想在此处删除useEffect()
怎么办? 它强烈反对 React 哲学吗? 这对我来说很有意义,因为我实际上不想在其他东西更改作为initialValue
传递的值时更新此输入值。 我不希望用户在发生这种情况时丢失他们的输入。
有多糟糕?
本质上,使用 prop 作为 state 变量 AFAIK 的初始值并没有错。
但是,在您的示例中,您正在做一些荒谬的事情:您正在定义一个 state 变量,该变量使用道具的值进行初始化,然后每次道具更新时,您都会使用相同的值更新您的 state 。 不管它是否是反模式,它都没有意义 - 直接使用 prop,你正在做无利可图的额外工作。 如果您删除useEffect
,您将非常有效地使用 prop 作为 state 变量的初始值。
在 React.js 中使用派生 state 的问题经常被误解, 这个 StackOverflow 问题证明了这一点。
在问题提供的代码示例中,不清楚为什么在可以直接使用initialValue
道具时使用派生的 state。 为了清楚起见,为此目的使用useEffect
将被视为反模式。 相反,您应该自己检查更改,如React 文档中所示
但是,如果EmailInput
组件对initialValue
做了一些修改,如果我们遵循“提升 state 的规则” (我相信作者试图在此评论中解释),这样的逻辑将不必要地污染父组件。
在这种情况下,我认为如果谨慎使用,反模式可能是一个可以接受的选择。 使用上述反模式的Robin Wieruch 博客文章。
另一种解决方案是使用key
属性( 在这种情况下很有用),但这仅在 key 和initialValue
基于不同状态时才有效。 否则,可能会导致重复渲染。
具有key
属性的示例
// EmailInput.jsx
export default function EmailInput({ initialValue, onChange }) {
const [value, setValue] = useState(initialValue);
const handleChange = (event) => {
const newValue = event.target.value;
// do some modification on the newValue
setValue(newValue);
onChange(newValue); // pass value to parent
};
return (
<>
<h1>The Email is {value}</h1>
<input type="text" value={value} onChange={handleChange} />
</>
);
}
// Checkout.jsx
export function Checkout() {
const [user, setUser] = useState({
id: 1,
email: "example@example.com",
});
return (
<>
<EmailInput
initialValue={user.email}
key={user.id}
onChange={(value) => setUser({ id: user.id, email: value })}
/>
<button
onClick={() => setUser({id: 2, email: "foo@bar.com"})}
>
Update user
</button>
</>
);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.