簡體   English   中英

沒有在函數內部獲取更新的鈎子值

[英]Not getting updated hooks value inside function

未在由 eventListener 觸發的函數中獲取狀態的更新值。 甚至嘗試使用后台計時器。 會有什么問題?

displayIncomingCall() // this function gets called from UI.
const callApp = () => {
  const [calls, setCalls] = useState({});

  const addCall = (key, value) => {
    setCalls({ ...calls, [key]: value });
  };

  const displayIncomingCall = number => {
    const callUUID = getCurrentCallId();
    addCall(callUUID, number);
    ...
  };

  const onAnswerCall = () => {
    console.log('=== onAnswerCall ::: ===', calls); <--- always initial value. Not getting updated one.
  }

  useEffect(() => {
    console.log('=== useEffect ::: ===', calls); // getting updated value
  }, [calls]);

  useEffect(() => {
    RNCallKeep.addEventListener('answerCall', onAnswerCall);
    return () => {
      RNCallKeep.removeEventListener('answerCall', onAnswerCall);
    };
  }, []);

  console.log('=== parent ::: ===', calls); // getting updated value

  return (...)
}

onAnswerCall只在useEffect回調中被引用,而useEffect回調有一個空的依賴數組,所以它只在初始掛載上運行。 每當onAnswerCallcalls ,它可以看到的calls綁定在一個舊的閉包中。

使用 ref 而不是 state:

const callsRef = useRef({});
const addCall = (key, value) => {
  callsRef.current[key] = value;
};
const onAnswerCall = () => {
  console.log('=== onAnswerCall ::: ===', callsRef.current);
}

如果calls需要處於狀態以便其更改導致重新渲染,那么您可以同時使用狀態和引用,並在調用setCalls時分配給引用,或者您可以從useEffect刪除依賴數組,因此在每次渲染時向RNCallKeep添加和刪​​除偵聽器。

React hooks state 不保留任何狀態數據,您必須使用useCallbackset* state 函數中的先前狀態來跟上您的狀態:

const callApp = () => {
  const [calls, setCalls] = useState({});

  const addCall = (key, value) => {
    // Use previous state provided to update the state
    setCalls(calls => ({ ...calls, [key]: value }));
  };

  const displayIncomingCall = number => {
    const callUUID = getCurrentCallId();
    addCall(callUUID, number);
    ...
  };

  //  Use useCallback to keep up  with the  state
  const onAnswerCall = useCallback(() => {
    console.log('=== onAnswerCall ::: ===', calls); <--- Will get updated
  }, [calls]);

  useEffect(() => {
    console.log('=== useEffect ::: ===', calls); // getting updated value
  }, [calls]);

  useEffect(() => {
    RNCallKeep.addEventListener('answerCall', onAnswerCall);
    return () => {
      RNCallKeep.removeEventListener('answerCall', onAnswerCall);
    };
  }, [onAnswerCall]);

  console.log('=== parent ::: ===', calls); // getting updated value

  return (...)
}

您的事件偵聽器回調在calls的初始狀態下關閉。 將其添加為效果的依賴項,並且每次其值更改時您都應該注冊一個新的偵聽器(並刪除舊的偵聽器)。

編輯:實際上,您應該將整個onAnswerCall函數移動到效果中,因為它只在那里使用:

useEffect(() => {
  const onAnswerCall = () => {
    console.log('=== onAnswerCall ::: ===', calls);
  };

  RNCallKeep.addEventListener('answerCall', onAnswerCall);
  return () => {
    RNCallKeep.removeEventListener('answerCall', onAnswerCall);
  };
}, [calls]);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM