如何解决无法获取函数内部更新的挂钩值
未获得由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
回调具有一个空的依赖项数组,因此它仅在初始安装时运行。每当调用onAnswerCall
时,它可以看到的calls
的绑定就在旧的闭包中。
使用ref代替状态:
const callsRef = useRef({});
const addCall = (key,value) => {
callsRef.current[key] = value;
};
const onAnswerCall = () => {
console.log('=== onAnswerCall ::: ===',callsRef.current);
}
如果calls
需要处于状态,以便其更改导致重新渲染,那么您可以同时使用 状态和ref,并在调用setCalls
时分配给ref,或者可以从useEffect
中删除依赖项数组,从而在每个渲染器上为RNCallKeep
添加和删除侦听器。
反应挂钩状态不会保留任何状态数据,您必须使用useCallback
以及set*
状态函数中特权的前一个状态才能保持状态:
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 (...)
}
,
您的事件监听器回调在bc
的初始状态下关闭。将其添加为效果的依赖项,并且每次其值更改时都应注册一个新的侦听器(并删除旧的侦听器)。
编辑:实际上,您应该将整个calls
函数移到效果中,因为它仅在此处使用:
onAnswerCall
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。