Reactjs 未在函数内获取更新的钩子值

Reactjs 未在函数内获取更新的钩子值,reactjs,react-native,react-hooks,setstate,Reactjs,React Native,React Hooks,Setstate,未获取由eventListener触发的函数中状态的更新值。甚至尝试使用后台计时器。有什么问题吗 displayIncomingCall() // this function gets called from UI. onAnswerCall仅在useEffect回调中引用,并且useEffect回调具有空的依赖项数组,因此它仅在初始装载时运行。无论何时调用onAnswerCall,它可以看到的调用绑定都在旧的闭包中 使用ref而不是state: const callsRef = useRef

未获取由eventListener触发的函数中状态的更新值。甚至尝试使用后台计时器。有什么问题吗

displayIncomingCall() // this function gets called from UI.
onAnswerCall仅在useEffect回调中引用,并且useEffect回调具有空的依赖项数组,因此它仅在初始装载时运行。无论何时调用onAnswerCall,它可以看到的调用绑定都在旧的闭包中

使用ref而不是state:

const callsRef = useRef({});
const addCall = (key, value) => {
  callsRef.current[key] = value;
};
const onAnswerCall = () => {
  console.log('=== onAnswerCall ::: ===', callsRef.current);
}
如果调用需要处于状态,以便其更改导致重新渲染,则可以同时使用state和ref,并在调用setCalls时指定ref,也可以从useffect中删除依赖项数组,因此,在每个渲染中添加和删除RNCallKeep的侦听器。

onAnswerCall仅在useEffect回调中引用,并且useEffect回调具有空的依赖项数组,因此它仅在初始装载时运行。无论何时调用onAnswerCall,它可以看到的调用绑定都在旧的闭包中

使用ref而不是state:

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

如果调用需要处于状态,以便其更改导致重新呈现,则可以同时使用state和ref,并在调用setCalls时分配给ref,或者可以从useffect中删除依赖项数组,从而在每个呈现上添加和删除侦听器以保持RNCallKeep。

React hookes state不会保留任何状态数据,您必须使用useCallback和set*state函数中的前一个私有状态来跟上您的状态:

const callApp==>{ const[calls,setCalls]=useState{}; const addCall=key,value=>{ //使用提供的先前状态更新状态 setCallscalls=>{…调用,[键]:值}; }; const displayIncomingCall=number=>{ const calluid=getCurrentCallId; addcalluid,number; ... }; //使用useCallback跟踪状态 const onAnswerCall=useCallback=>{ console.log'==onAnswerCall::===',调用{ console.log'==useffect::===',调用;//获取更新值 },[电话]; useEffect=>{ RNCallKeep.addEventListener'answerCall',onAnswerCall; 返回=>{ RNCallKeep.removeEventListener'answerCall',onAnswerCall; }; },[onAnswerCall]; console.log'==父项::===',调用;//获取更新值 回来 }
React hooks state不会保留任何状态数据,您必须使用useCallback和set*state函数中的前一状态来保持您的状态:

const callApp==>{ const[calls,setCalls]=useState{}; const addCall=key,value=>{ //使用提供的先前状态更新状态 setCallscalls=>{…调用,[键]:值}; }; const displayIncomingCall=number=>{ const calluid=getCurrentCallId; addcalluid,number; ... }; //使用useCallback跟踪状态 const onAnswerCall=useCallback=>{ console.log'==onAnswerCall::===',调用{ console.log'==useffect::===',调用;//获取更新值 },[电话]; useEffect=>{ RNCallKeep.addEventListener'answerCall',onAnswerCall; 返回=>{ RNCallKeep.removeEventListener'answerCall',onAnswerCall; }; },[onAnswerCall]; console.log'==父项::===',调用;//获取更新值 回来 }
您的事件侦听器回调在调用的初始状态下关闭。将其作为依赖项添加到效果中,您应该注册一个新的侦听器,并在每次其值更改时删除旧的侦听器

编辑:实际上,您应该将整个onAnswerCall函数移动到效果中,因为它仅在那里使用:

useEffect=>{ const onAnswerCall==>{ console.log'==onAnswerCall::===',调用; }; RNCallKeep.addEventListener'answerCall',onAnswerCall; 返回=>{ RNCallKeep.removeEventListener'answerCall',onAnswerCall; }; },[电话];
您的事件侦听器回调在调用的初始状态下关闭。将其作为依赖项添加到效果中,您应该注册一个新的侦听器,并在每次其值更改时删除旧的侦听器

编辑:实际上,您应该将整个onAnswerCall函数移动到效果中,因为它仅在那里使用:

useEffect=>{ const onAnswerCall==>{ console.log'==onAnswerCall::===',调用; }; RNCallKeep.addEventListener'answerCall',onAnswerCall; 返回=>{ RNCallKeep.removeEventListener'answerCall',onAnswerCall; }; },[电话];
这是因为当组件首次装入时,您只添加了一次EventListener,而在重新呈现组件时不更新它。它始终在调用的初始值上关闭。请尝试在SetState中添加return,这是因为当组件首次装入时,您只添加了一次EventListener,而在组件装入时不更新它已重新呈现。它始终在调用的初始值上关闭。请尝试在SetState中添加return。这将起作用,但不会成功

更新调用时不要重新渲染组件,我认为调用是在组件渲染上使用的,因此我估计它需要触发重新渲染。由于看不到组件的返回值,因此不清楚在进行新调用时组件是否需要重新渲染。如果它确实需要重新渲染,那么就像我说的,一种方法是同时使用ref和state。另一种方法是在每次调用时添加和删除侦听器。使用状态而不是普通变量的要点是让React触发组件重新呈现。如果您检查我的答案,每次onAnswerCall useCallback更新时都会删除/添加侦听器,我认为这是最好的方法,这就是这些挂钩的目的。如果变量更改时需要重新呈现,则是,当然要使用state,但是从问题中的代码来看,我不清楚是否需要这样的重新渲染。组件返回的JSX没有显示,不幸的是,现在还没有在渲染中使用。如果我们也有重新渲染的灵活性,那就更好了。此解决方案可以工作。这可以工作,但在更新调用时不会重新呈现组件。我认为调用在组件呈现上使用,因此我建议它需要触发重新呈现。由于看不到组件的返回值,因此不清楚在进行新调用时组件是否需要重新呈现。如果它确实需要重新渲染,那么就像我说的,一种方法是同时使用ref和state。另一种方法是在每次调用时添加和删除侦听器。使用状态而不是普通变量的要点是让React触发组件重新呈现。如果您检查我的答案,每次onAnswerCall useCallback更新时都会删除/添加侦听器,我认为这是最好的方法,这就是这些挂钩的目的。如果变量更改时需要重新呈现,则是,当然要使用state,但是从问题中的代码来看,我不清楚是否需要这样的重新渲染。组件返回的JSX没有显示,不幸的是,现在还没有在渲染中使用。如果我们也有重新渲染的灵活性,那就更好了。这个解决方案有效,你为什么要这样做?你认为调用更改后onAnswerCall会有所不同吗?@Christolytras它在每个渲染上都是不同的函数,所以是的!但它的返回值实际上只是在调用更改时不同。这里有一支笔说明了控制台上的这种情况:我的问题是有点遗漏了引导,我指的是调用change state,而不是renders。我认为正确的方法是使用useCallback,只有在调用发生更改时才获取新函数,然后重新应用侦听器。在这里用这个逻辑检查一下你的例子,我不认为我们有分歧——这两种解决方案都做了完全相同的事情,你有更少的不必要的函数创建,但在JS中这真的很快。我试图指出OP对事件听众工作方式的误解。那么,同意不同意吧。肯定有一个时间和地点用于useCallback,我每天都会使用它。我只是觉得你不需要它,因为效果和功能都取决于同一个东西的变化。你为什么要这样做?你认为调用更改后onAnswerCall会有所不同吗?@Christolytras它在每个渲染上都是不同的函数,所以是的!但它的返回值实际上只是在调用更改时不同。这里有一支笔说明了控制台上的这种情况:我的问题是有点遗漏了引导,我指的是调用change state,而不是renders。我认为正确的方法是使用useCallback,只有在调用发生更改时才获取新函数,然后重新应用侦听器。在这里用这个逻辑检查一下你的例子,我不认为我们有分歧——这两种解决方案都做了完全相同的事情,你有更少的不必要的函数创建,但在JS中这真的很快。我试图指出OP对事件听众工作方式的误解。那么,同意不同意吧。肯定有一个时间和地点用于useCallback,我每天都会使用它。我只是觉得你不需要它,因为效果和功能都取决于同一事物的变化。但是onAnswerCall会被触发多次侦听器只调用一次侦听器将注销旧的侦听器,并在每次调用更新时注册新的侦听器,这不会影响answerCall事件被触发的次数,也不会影响事件侦听器调用onAnswerCall的次数。与onAnswerCall一样,我也有类似的4-5调用状态事件侦听器,我在代码段中没有提到。正如我所读到的,如果我们对所有的事件侦听器使用useCallback,它会影响性能吗?执行的每一行代码都会带来成本—您将得到的性能影响对于所有侦听器每个事件一个额外的函数调用是微不足道的。很明显,当你调用2个函数而不是1个函数时,有很多工作要做,不是吗?如果您只是对侦听器使用这些函数,请将它们直接放在
挂载效果,否则您没有选择如果在呈现方法中使用调用状态,则必须使用useCallback。但是onAnswerCall被触发多次侦听器仅调用一次侦听器将注销旧的侦听器,并在每次调用更新时注册新的侦听器,这不会影响answerCall事件被触发的次数,也不会影响事件侦听器调用onAnswerCall的次数。与onAnswerCall一样,我也有类似的4-5调用状态事件侦听器,我在代码段中没有提到。正如我所读到的,如果我们对所有的事件侦听器使用useCallback,它会影响性能吗?执行的每一行代码都会带来成本—您将得到的性能影响对于所有侦听器每个事件一个额外的函数调用是微不足道的。很明显,当你调用2个函数而不是1个函数时,有很多工作要做,不是吗?如果您只是对侦听器使用这些函数,请将它们直接放置在mount effect中,否则,如果您在渲染方法中使用calls状态,则您没有选择权,您必须使用useCallback。