【问题标题】:useContext not updating its value in callbackuseContext 未在回调中更新其值
【发布时间】: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);
    };
  }, []);
};

【问题讨论】:

    标签: javascript reactjs closures react-hooks


    【解决方案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]);
    };
    

    友情提示:

    【讨论】:

    • 您能否详细说明为什么原始解决方案不起作用?这是否意味着每次调用 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,所以在卸载发生后。
    猜你喜欢
    • 2021-08-23
    • 2021-01-23
    • 2020-05-03
    • 2021-07-02
    • 2020-03-25
    • 1970-01-01
    • 1970-01-01
    • 2019-12-24
    相关资源
    最近更新 更多