--- tags: React.js --- # React Hook Form & React Context ## React Hook Form 使用教學 這是一個表單套件 可以直接進入[官網](https://react-hook-form.com/form-builder)設定好需要的表單欄位與驗證內容 送出後右邊就會自動產出程式碼給你複製使用 範例: ```jsx= function App() { const { register, // 註冊表單欄位 handleSubmit, // 處理提交事件 formState: { errors } // 處理錯誤狀態 } = ReactHookForm.useForm(); const onSubmit = (data) => alert(JSON.stringify(data)); console.log(errors); // data 是 object 裡面放 { inputName: inputValue } return ( <form onSubmit={handleSubmit(onSubmit)}> <input type="text" placeholder="First name" {...register("First name", { required: true, min: 3, maxLength: 80 })} // 這裡是註冊語法 (inputName, {輸入框條件}) /> <input type="submit" /> </form> ); } const root = ReactDOM.createRoot(document.getElementById("root")); root.render(<App />); ``` ## React Hook Form 錯誤提示作法 ### 一、沒填寫或格式錯誤統一顯示某段文字 ```jsx= <form onSubmit={handleSubmit(onSubmit)}> <div> 帳號: <input placeholder="帳號" name="account" {...register("account", { required: true })} /> {errors.account && <span>錯誤訊息內容</span>} </div> <div> 密碼: <input name="password" type="password" placeholder="密碼" {...register("password", { required: true })} /> {errors.password && <span>錯誤訊息內容</span>} </div> <input type="submit" /> </form> ``` 針對 `{errors.account && <span>錯誤訊息內容</span>}` 說明: && 是邏輯運算子,規則是 ```htmlmixed= 當左邊可解析成 false 就會回傳左邊的東西 當左邊可解析成 true 就會直接回傳右邊的東西 當左右兩邊都是 True 時才會回傳 True,否則回傳 false ``` 所以當 errors.account 有內容,就會回傳右邊的 `<span>錯誤訊息內容</span>` ### 二、根據不同狀況提示不同錯誤 ```jsx= <input type="email" placeholder="email" {...register("email", { required: { value: true, message: "此欄位必填寫" }, pattern: { value: /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/g, message: "不符合 Email 規則" } })} /> {errors.email?.message} ``` 當 required 為 true 但沒有填寫,`{errors.email?.message}` 就會是 `"此欄位必填寫"` 當有填寫但格式錯誤,`{errors.email?.message}` 就會是 `"不符合 Email 規則"` ## Context 概念上類似 windows 的全域變數 在最外層建立的東西可以被其他區域查找並使用 範例: ```jsx= const MyContext = React.createContext(); // 建立全域環境 function ThemeText() { const theme = React.useContext(MyContext); // 抓取環境傳入的變數 return ( <p style={{ color: theme.background }}> 我是 theme 中的 light background 色的文字 </p> ); } function App() { const themes = { light: { foreground: "#ffffff", background: "#313675" } }; return ( // 屬性 value 傳入要共享的資料,MyContext.Provider 裡面包元件 <MyContext.Provider value={themes.light}> <ThemeText /> </MyContext.Provider> ); } const root = ReactDOM.createRoot(document.getElementById('root')); root.render(<App />); ``` ### 把 useContext 整成一個 import 的檔案 基本用法就是先建立一個環境 => const AuthContext = createContext() 接著在要用到的地方抓取這個環境 => useContext(AuthContext) 所以根據 import/export 的方式可以獨立拆成一個檔案 `Context.js`, 檔案內容如下: ```jsx= import { createContext, useContext } from "react"; export const AuthContext = createContext(null); // 匯出 AuthContext 這個參數 => 等同於上一段範例中的 const MyContext = React.createContext(); export const useAuth = () => { // 匯出 useAuth 這個函數 => 等同於上一段範例中的 const theme = React.useContext(MyContext); return useContext(AuthContext); }; ``` 建立好 Context.js 後,最主要的 App.js 就可以用 `AuthContext.Provider` 標籤 通過屬性 value ,傳入共用資料 { token, setToken } 讓 `AuthContext.Provider` 標籤包裹著的元件們都可以使用這個共用資料了 如下: ```jsx= function App() { const [token, setToken] = useState(null); return ( <div className="App"> <AuthContext.Provider value={{ token, setToken }}> <Routes> <Route path="signUp" element={<SignUp />} /> <Route path="Login" element={<Login />} /> </Routes> </AuthContext.Provider> </div> ); } ``` > 說明一下 `<AuthContext.Provider value={{ token, setToken }}>` > 因為 React 可以省去雙引號通過 xxx={xxx} 傳東西 > 剛好要傳進去的又是物件 { token, setToken } > 所以 value={共用資料} 就變成 value={{ token, setToken }} > 實際傳入的還是物件 { token, setToken } 不是 {{ token, setToken }} 哦! 元件檔案想使用共用資料時, 在元件檔案最開頭 `import { useAuth } from "./Context";` 接著通過 `const { token, setToken } = useAuth()` => 物件解構方式 就可以像正常 useState() 一樣讀取 token、通過 setToken 設定 token 囉