
React 提供了函式型元件(Function Component)和類別型元件(Class Component)兩種寫法,而 React Hooks 為函式型元件提供了簡潔的工具來管理 state,同時保有強大的功能。然而,若沒有正確使用 hooks,可能會導致效能問題與難以除錯的程式碼。本文我們將探索 React Hooks 的使用方法及注意事項。
React Hooks 大致上有兩個主要規則:
只能在最上層呼叫 hooks: 不要在迴圈、條件判斷或巢狀函式中呼叫 hooks。
只能在 React 函式中呼叫 hooks: Hooks 必須用在函式型元件(Function Component)或自訂 hook 中。
這些規則確保 hooks 在每次 render 中都以相同順序呼叫,避免不可預期的行為。
使用 useState 時,請注意以下情況:
避免不必要的 state 更新:如果下一個 state 需要根據前一個 state 來做更新,最好使用函式形式的更新方式。
jsx1const [count, setCount] = useState(0); 2 3const increment = () => { 4 setCount(prevCount => prevCount + 1); 5};
避免將可推導的值放進 state: 若某個值可以從既有 state 或 props 推導計算,就不需要額外存進 state。
useMemo:記住昂貴的計算以避免不必要的重新計算。
jsx1const computedValue = useMemo(() => heavyComputation(input), [input]);
useCallback:記憶函式引用,以避免子元件的無謂重新渲染。
js1const handleClick = useCallback(() => { 2 console.log("Clicked!"); 3}, []);
useEffect 用於處理 side effects,例如資料抓取或事件訂閱。建議:
正確指定 dependencies: 永遠將依賴的變數放進 dependency array,以免使用到舊值(stale values)來更新。
清除 side effects: 使用事件監聽或訂閱時,回傳 cleanup 函式來清除資源。
jsx1useEffect(() => { 2 const handleResize = () => console.log(window.innerWidth); 3 window.addEventListener("resize", handleResize); 4 5 return () => { 6 window.removeEventListener("resize", handleResize); 7 }; 8}, []);
若多個元件會用到相同邏輯,可以將邏輯封裝成自訂 hook:
jsx1function useWindowWidth() { 2 const [width, setWidth] = useState(window.innerWidth); 3 4 useEffect(() => { 5 const handleResize = () => setWidth(window.innerWidth); 6 window.addEventListener("resize", handleResize); 7 return () => window.removeEventListener("resize", handleResize); 8 }, []); 9 10 return width; 11}
這樣能讓程式碼更具重複使用性且更易維護。
本文列出幾項官方建議的 best practice,讓我們透過 React Hooks 撰寫高效、易維護且優化過的元件,遵循這些 best practice,就可以更輕鬆的正確管理 state 和 side effects!