[英]Synchronizing state in custom hooks
TL/DR:
如何正確同步兩個鈎子之間的狀態?
實施細節:
我將簡化示例並使用
useState
,而不是使用我實際使用的第一個自定義鈎子來簡化問題。本質上,省略的鈎子的作用是返回
state
和輔助函數。 所以只是為了畫圖:const [email, onEmailChange, onEmailBlur] = useField('init', isEmailValid)
被簡單地替換(盡管它在技術上是多余的)
const [email, setEmail] = useState('hi')
我在這里留下這段摘錄的原因是我沒有得到關於初始
useState
是多余的評論/答案
什么有效:
將 state 引用傳遞給簡單地返回它的基本 function 引用。
const useForm = (...fields) => {
return {
fields,
}
}
const form = useForm(email) // updates correctly
問題開始的地方:
現在顯然這東西甚至不需要鈎子。 當我嘗試添加更復雜的邏輯時出現問題
const useForm = (submitFunction, ...fields) => {
const initialForm = {
fields,
wasSubmitted: false,
}
const [form, setForm] = useState(initialForm)
const handleSubmit = (event) => {
event.preventDefault()
if (!fields.some(({ error }) => !!error) {
submitFunction()
}
setForm({
fields,
wasSubmitted: true,
})
}
return [form, handleSubmit] // now the state no longer updates
}
現在我確實懷疑為什么會發生這種情況。 僅僅因為
useState
初始化了 state 的新實例,所以我們只是從傳遞的狀態返回初始化值。
問題是,我無法真正了解如何同步這些。
具有工作和非工作掛鈎的可編輯示例:
正如您所提到的,這是因為useState
中的useForm
正在設置form
state 的初始值,並且它的值在下一次渲染中不會改變。
如果要保持form
和fields
同步,可以使用useEffect
每次fields
中的值更改時更新form
的值。
...
const [form, setForm] = useState<Form>(initialForm);
useEffect(() => {
setForm(formState => ({ ...formState, fields }))
}, fields);
...
此解決方案的問題在於, setForm
中的useEffect
會在每次fields
中的值更改時導致另一個重新渲染。
解決此問題的另一種方法是不在 state 中保存fields
值,而僅將wasSubmitted
保留在 useForm 的useForm
中。
const useForm = (submitFunction, ...fields) => {
const [wasSubmitted, setWasSubmitted] = useState(false);
const handleSubmit = (event) => {
if (fields.some(field => field === "run")) {
submitFunction();
}
setWasSubmitted(true);
};
return [{ fields, wasSubmitted }, handleSubmit];
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.