未获得由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 (...)
}
答案 0 :(得分:1)
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
添加和删除侦听器。
答案 1 :(得分:1)
反应挂钩状态不会保留任何状态数据,您必须使用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 (...)
}
答案 2 :(得分:1)
您的事件监听器回调在bc
的初始状态下关闭。将其添加为效果的依赖项,并且每次其值更改时都应注册一个新的侦听器(并删除旧的侦听器)。
编辑:实际上,您应该将整个calls
函数移到效果中,因为它仅在此处使用:
onAnswerCall