我在组件中有一个组件。由于复杂的计算,父组件(窗体)的渲染成本很高。因此,如果我在子组件(UserForm)的用户名输入中按住一个键,该页面将开始丢弃帧(新字符不会显示一点),因为它会尽快渲染父项(这很昂贵) 。为了解决这个问题,我开始将用户名prop的本地实例存储在子组件中的状态中,然后在将该状态传递给父级之前将其去抖。
问题是,当子组件中的反跳仍在进行时,当父组件修改用户名(例如通过还原更改)时,父子组件的反跳输出会覆盖父组件的修改。
const UserForm = ({ value, onChange }) => {
const debouncedOnChange = useCallback(
lodash.debounce(updatedValue => {
onChange(updatedValue);
}, 500),
[onChange]
);
const [username, setUsername] = useState(value.username);
useEffect(() => {
setUsername(value.username);
}, [value.username]);
const handleUsernameOnChange = useCallback(
event => {
setUsername(event.target.value);
debouncedOnChange({
...value,
username: event.target.value,
});
},
[debouncedOnChange]
);
return (
<div>
<input value={username} onChange={handleUsernameOnChange} />
</div>
);
};
const INITIAL_STATE = {
user: {
username: 'John',
},
dog: {
name: 'Cliffard'
}
};
// <Form/> Is expensive to render because of complex calculations
const Form = () => {
const [value, setValue] = useState(INITIAL_STATE);
const [backup, setBackup] = useState(INITIAL_STATE);
return (
<form>
<UserForm
value={value.user}
onChange={updatedUserFormValue => {
setValue({
...value,
updatedUserFormValue,
});
}}
/>
<button
onClick={() => {
setValue({
...value,
user: { ...backup.user },
});
}}
>
Reset User Form
</button>
</form>
);
};