前情提要:上一篇把 page.tsx 中的表單部分重構整理成一個新的元件,不過搬移的過程中,有一些問題沒有處理好,所以這篇就來處理一下。
errors 到 page.tsx從 React Hook From 中的 errors 因為目前都在 CreateSvgForm.tsx 中,所以要把 errors 傳遞到 page.tsx 中,這樣才能在 page.tsx 中顯示錯誤訊息。
傳遞的方式有很多,因為我們已經使用 Zustand 來管理狀態了,所以可以直接把 errors 存到 Zustand 中,然後在 page.tsx 中取出就可以了。
errors 到 store第一步先把狀態的部分弄好,所以先在 store/index.ts 中新增以下的部分:
import { create } from 'zustand'
import { FieldError } from 'react-hook-form'
type ErrorType = {
  text?: FieldError
  qrType?: FieldError
  qrSize?: FieldError
  qrColor?: FieldError
  qrBgColor?: FieldError
}
interface Store {
  imgSrc: string | null
  setImgSrc: (imgSrc: string | null) => void
  errorsFromForm: ErrorType
  setErrors: (errors: ErrorType) => void
}
const useStore = create<Store>((set) => ({
  imgSrc: null,
  setImgSrc: (imgSrc) => set({ imgSrc }),
  errorsFromForm: {},
  setErrors: (errors) => set({ errorsFromForm: errors })
}))
export default useStore
這裡先定義了 ErrorType 這個型別,然後在 Store 中新增了 errorsFromForm 這個狀態,並且定義了 setErrors 這個方法。
然後為了避免搞混,所以把 errors 改名為 errorsFromForm,這樣就不會跟 React Hook Form 中的 errors 搞混了。
要注意的部分,
ErrorType的型別最好從react-hook-form中取得,這樣才不會有錯誤。
CreateSvgForm 元件中取得 errors接下來就可以在 CreateSvgForm.tsx 中取得 errors 了,只要從 useForm 中取得 setErrors,然後在 useEffect 中把 errors 存到 Zustand 中就可以了:
const { setImgSrc, setErrors } = useStore()
useEffect(() => {
  setErrors(errors)
}, [errors])
最後在 page.tsx 中取得 errorsFromForm 就可以了:
export default function Home() {
  const { imgSrc, errorsFromForm } = useStore()
  const hasErrors = Object.keys(errorsFromForm).length > 0
  return (
    <main className='flex min-h-screen flex-col items-center justify-between p-24'>
      <div className='container mx-auto p-4'>
        <h1 className='text-3xl mb-4'>QR Code 製造器</h1>
        <CreateSvgForm />
        {imgSrc && Object.keys(errorsFromForm).length < 1 ? (
          <div className='flex justify-center mt-10'>
            <Image src={imgSrc} width={500} height={500} alt='QR Code Image' />
          </div>
        ) : (
          <p>
            {hasErrors
              ? '請輸入正確的資訊'
              : '請點擊「產生 QR Code」按鈕'}
          </p>
        )}
      </div>
    </main>
  )
}
可以正常運作就沒問題了👍。

這篇文章用 Zustand 解決了狀態在不同元件間的傳遞問題,是不是感受到了狀態管理的便利性呢?明天來新增 PNG 的表單元件,明天見👋!