javascript - 如何在多個依賴同時變化時只運行一次 useEffect
我正在使用一個帶有兩個依賴項的 useEffect 鉤子,如下所示:
useEffect(() => { ..... }, [apiData, currentMeasurements]);
請注意,apiData 是透過 apollo/client 的 useLazyQuery 獲取的。
現在在儲存時(例如,儲存或提交表單),兩個依賴項會同時改變,即 apiData 被獲取,currentMeasurements 也使用 setState 設置為新陣列(即 setCurrentMeasurements([]))。
由於 API 呼叫需要時間,當 currentMeasurements 被設置時,React 會執行一次 useEffect,當我收到 API 回應時,又會再執行一次。
但這不是預期的行為。這會導致在 useEffect 被渲染時(因為 currentMeasurements 的變化)畫面上首次呈現舊的數值,然後幾秒鐘後,當 useEffect 再次運行(因為我們獲取了 newApiData)時,新數據才會被渲染。
如何讓 useEffect 僅在我收到 API 回應時運行?或者換句話說,如何讓 useEffect 僅在我獲得要傳入 useEffect 的兩個依賴項準備好時才運行。
我嘗試過但不起作用的事情:使用 setTimeOut(設定自訂時間)來更新 currentMeasurements,但當 API 回應延遲時,這會造成問題。
答案#1
你可以將兩個依賴項都儲存為 refs,然後檢查兩者是否都改變。如果沒有,什麼都不做。如果改變了,更新 ref。
const changedRef = useRef({});
useEffect(() => {
if(changedRef.current.currentMeasurements !== currentMeasurements &&
changedRef.current.apiData !== apiData) {
... // do something
changedRef.current = {
apiData
currentMeasurements
};
}
}, [apiData, currentMeasurements]);
然而,使用中斷條件更容易——即如果 currentMeasurements 的長度為 0,則不要在 useEffect 中執行任何操作:
useEffect(() => {
if(currentMeasurements.length === 0) return;
... // do something
}, [apiData, currentMeasurements]);
答案#2
你可以比較它們的初始值,如果其中任何一個持續存在,就不要執行副作用
useEffect(()=>{
if(currentMeasurements.length == 0 || apiData == InitialValue) return;
// do something with apiData and currentMeasurements
}, [apiData, currentMeasurements])
