簡體   English   中英

在自定義掛鈎中同步 state

[英]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 的新實例,所以我們只是從傳遞的狀態返回初始化值。

問題是,我無法真正了解如何同步這些。

具有工作和非工作掛鈎的可編輯示例

編輯充滿活力的-darwin-8s1cv

正如您所提到的,這是因為useState中的useForm正在設置form state 的初始值,並且它的值在下一次渲染中不會改變。

如果要保持formfields同步,可以使用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM