useContext 未在回调中更新其值
Posted
技术标签:
【中文标题】useContext 未在回调中更新其值【英文标题】:useContext not updating its value in callback 【发布时间】:2020-02-16 23:12:21 【问题描述】:useConext
值在我附加到wheel
事件的回调中没有更新。我试图安慰但仍在打印静态值。但在回调之外,它正在打印更新的值
const Home = () =>
//accessing my context
var [appState, dispatch] = useContext(CTX);
//printing updated value here (working perfect here)
console.log(appState);
//my callback on wheel event (also using debouce to queue burst of events)
var fn = debounce(e =>
//incrementing value ++1
dispatch( type: 'INCREMENT_COMPONENT_COUNTER' );
//printing static value here (problem here)
console.log(appState);
, 500);
//setting and removing listener on component mount and unmount
useEffect(() =>
window.addEventListener('wheel', fn);
return () =>
window.removeEventListener('wheel', fn);
;
, []);
;
【问题讨论】:
【参考方案1】:在挂载时,侦听器使用一个函数变量进行初始化,该变量将appStore
的第一个值包含在其词法范围内。
请参阅Closures。
要修复它,请将其移动到 useEffect
范围内。
const Home = () =>
const [appState, dispatch] = useContext(CTX);
useEffect(() =>
const fn = debounce(e =>
dispatch( type: 'INCREMENT_COMPONENT_COUNTER' );
console.log(appState);
, 500);
window.addEventListener('wheel', fn);
return () =>
window.removeEventListener('wheel', fn);
;
, [appState]);
;
友情提示:
使用linter likeeslint
- 它应该警告你在useEffect
中使用appState
Don't use var
- 容易出错。
【讨论】:
您能否详细说明为什么原始解决方案不起作用?这是否意味着每次调用 dispatch 时 appState 都会发生变化? (即,appState 不是指针,因此它始终包含原始值)。appState
上有一个闭包,所以它的值在下一次渲染时是陈旧的
嗯,是的,但是如果 appState 是一个指针,那不会有问题,因为 appState 本身不会改变,但它指向的值会。我不确定是否真的了解这里发生的事情。
即使它是一个“指针”appState=someValue
,如果 appState
对象会改变:appState=someValue, otherValue
监听器中的值将是陈旧的。
所以如果我理解正确,dispatch
正在修改appState
的值而不是对象本身,这就是为什么它不起作用? (这里是my question,没有歧义)【参考方案2】:
您的 debance 函数在每次渲染中都会发生变化,而 useEffect 仅捕获第一个渲染,您可以使用 useCallback 解决此问题:
const Home = () =>
// accessing my context
const [appState, dispatch] = useContext(CTX)
// printing updated value here (working perfect here)
console.log(appState)
// my callback on wheel event (also using debouce to queue burst of events)
const fn = useCallback(
() =>
debounce(e =>
// incrementing value ++1
dispatch( type: 'INCREMENT_COMPONENT_COUNTER' )
// printing static value here (problem here)
console.log(appState)
, 500),
[appState, dispatch],
)
// setting and removing listener on component mount and unmount
useEffect(() =>
window.addEventListener('wheel', fn)
return () =>
window.removeEventListener('wheel', fn)
, [fn])
【讨论】:
仍然无法正常工作。由于您在 useEffect 依赖数组中添加了 fn,因此它在每次 fn 更新时都附加了 wheel 事件。我将这个数组留空的原因是这个 useEffect 只会在 mount 和 unmount 监听器上运行一次,因为我在 useEffect 中添加了 return,所以在卸载发生后。以上是关于useContext 未在回调中更新其值的主要内容,如果未能解决你的问题,请参考以下文章
useContext 未在子组件中显示更新的状态(当从全局文件中的 useEffect 挂钩中的 firebase 检索数据时)
useState 中的变量未在 useEffect 回调中更新