繁体   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