给组件添加key属性,重置时更新key
适用于:整个组件的重置,包含组件的state数据
如一个用户邮箱输入组件,从父组件接受初始值,组件内部可以重新输入。
// EmailInput 组件
const EmailInput: React.FC<IProp> = props => {
const [email, setEmail] = useState(props.defaultEmail);
const handleChange = event => {
setEmail(event.target.value);
};
return <input onChange={handleChange} value={email} />;
}
此时,如果希望在父组件中可以切换不同的用户,切换后输入框需重置为当前用户的默认邮箱。我们可以使用 key 这个特殊的 React 属性。当 key 变化时, React 会创建一个新的而不是更新一个既有的组件。
<EmailInput
defaultEmail={user.email}
key={user.id}
/>
大部分情况下,这是处理重置 state 的最好的办法
如果某些情况下 key 不起作用,或者不太合适(如组件初始化的开销太大),又或者是我们只需要更新组件部分数据,可以考虑使用下面2种方式
根据props属性变更,更新数据
// EmailInput 组件
const EmailInput: React.FC<IProp> = props => {
const [email, setEmail] = useState(props.email);
useEffect(() => {
setEmail(props.email);
}, [props.id])
// ...
}
有些时候,我们没有合适的props属性来作为更新的依赖,也想重新创建组件。一种解决方案是给一个随机值或者递增的值当作 props 的值。
使用实例方法重置数据
在组件内部,定义相关的重置方法,然后父组件使用 ref 获取组件实例来调用这个方法。
子组件:通过 forwardRef 、useImperativeHandle 抛出内部方法
// EmailInput 组件
const EmailInput = forwardRef((props, ref) => {
const [email, setEmail] = useState(props.email);
const resetEmail = newEmail => {
setEmail(newEmail);
};
// 对父组件抛出内部方法
useImperativeHandle(ref, () => ({
resetEmail
}));
// ...
})
父组件:命令式调用组件内部方法
// 父组件
const FormInput: React.FC = () => {
const emailRef = useRef();
// ...
// 父组件调用自组件内部方法
const setEmail = (email) => {
emailRef.current.resetEmail(email);
}
return <EmailInput ref={emailRef} email={user.email} />
}
React 的思想是数据驱动视图,虽然通过这种方法也可以实现这种功能,不过还是更建议使用上面的2种方式。
总结:
对于非受控的组件,当想在 prop 变化时重置 state 的话,可以选择以下几种方式:
- 重置内部所有的初始
state,使用key属性 - 仅更改某些字段,观察特殊属性的变化(比如
props.userID)。 - 使用
ref调用实例方法。