為什么在 React 中使用對象類型作為 state 時,onChange 事件會觸發兩次?

為什么在 React 中使用對象類型作為 state 時,onChange 事件會觸發兩次?

React 中 onChange 事件觸發多次的解析

在 React 應用開發中,一個常見的困惑是:輸入框內容變化時,onChange 事件處理函數會被調用兩次。本文將分析這種現象,特別是當 state 使用對象類型時,為何會觸發兩次調用,而使用基本數據類型(如數字)時只會觸發一次。

問題示例:

import React, { useState } from "react";  export default function Child() {   const [state, setState] = useState({});    const onChange = (event) => {     console.log("onChange", state); //此處打印兩次     setState({...state, [event.target.name]: event.target.value});   };    return (     <div>       <input type="text" name="myInput" onChange={onChange} />     </div>   ); }

在這個例子中,每次輸入變化,onChange 函數和 console.log 語句都會執行兩次。

問題根源:React 嚴格模式

這并非代碼錯誤或環境問題,而是 React 的 嚴格模式 (StrictMode) 的設計特性。在開發環境中啟用嚴格模式,React 會故意進行兩次渲染,以幫助開發者盡早發現潛在問題。

嚴格模式會對某些函數進行雙重調用(僅限于應為純函數的函數)。第一次渲染用于檢測副作用,第二次渲染才是實際的 dom 更新。當 state 為對象類型時,由于對象是引用類型,React 會將其視為可能存在副作用,從而觸發雙重渲染和調用。而基本數據類型由于沒有副作用,則只會渲染一次。

解決方案

解決方法取決于你的需求:

  • 生產環境: 在生產環境中,嚴格模式默認禁用,因此這個問題不會出現。

  • 開發環境: 如果在開發環境中需要避免雙重調用,可以考慮以下幾種方法:

    • 使用 useCallback 鉤子: 將 onChange 函數用 useCallback 包裹,可以避免不必要的重新渲染和重復調用。
      const onChange = useCallback((event) => {       console.log("onChange", state);       setState({...state, [event.target.name]: event.target.value});   }, [state, setState]);
    • 檢查并避免不必要的 state 更新: 確保你的 setState 調用只在必要時進行,避免無意義的重復更新。 例如,可以使用函數式更新來避免不必要的重新渲染:
      setState(prevState => ({...prevState, [event.target.name]: event.target.value}));
    • 禁用嚴格模式 (不推薦): 可以在你的組件中禁用嚴格模式,但這會失去嚴格模式帶來的潛在問題檢測能力,因此不推薦。

總結

onChange 事件在 React 中觸發多次,通常是由于開發環境下的嚴格模式導致的雙重渲染。理解其原因,并根據實際情況選擇合適的解決方案,可以有效地解決這個問題,并提高代碼質量。 使用 useCallback 或函數式更新是推薦的解決方法,可以保持嚴格模式帶來的好處,同時避免不必要的重復渲染和函數調用。

? 版權聲明
THE END
喜歡就支持一下吧
點贊11 分享