前情提要:上一篇把 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 的表單元件,明天見👋!