【问题标题】:React state variable not accurate after set state in useState hook在 useState 挂钩中设置状态后反应状态变量不准确
【发布时间】:2020-02-22 00:55:28
【问题描述】:

我有一个与旧版 JQuery 应用程序一起运行的 React 函数组件。在 JQuery 元素上调用事件处理程序时,传入当前 React 状态默认为初始状态值,而不是更新后的状态值。

通过 useEffect 钩子验证 x 状态正在改变,但是在调用事件监听器时,x 被设置为初始状态值,而不是更新后的状态值。

function MyComponent(props) {
   const [x, setX] = useState(false);

// On initial render
useEffect(() => {
   props.jQueryButton.addEventListener('click', onXSave)
}, [])

useEffect(() => {
    console.log("x changed " + x); // everytime onXChange is called, x 
    state is updated with the checked value, and this console.log shows 
    the correct state value
}, [x]);

onXChange = event => {
   setX(event.target.checked); // checked is true in this context
};

onXSave = event => {
  const obj = { x: x}; // x is false here, even though the state in this context shows it to be true.
  };
}

不显示错误消息。在此上下文中的上述代码中,我希望 x 状态在 onXSave 方法调用中为 true,但它一直显示为 false。

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    onXSave 在初始渲染时添加为处理程序,因此x 具有当时的值。在每次渲染时重新创建onXSave 并不重要,因为它在初始渲染之后从未使用过。

    要解决此问题,您可以将 x 放入 ref

    unction MyComponent(props) {
       const [x, setX] = useState(false);
       const ref = useRef();
       ref.current = x;
    
    // On initial render
    useEffect(() => {
       props.jQueryButton.addEventListener('click', onXSave)
    }, [])
    
    useEffect(() => {
        console.log("x changed " + x); // everytime onXChange is called, x 
        state is updated with the checked value, and this console.log shows 
        the correct state value
    }, [x]);
    
    onXChange = event => {
       setX(event.target.checked); // checked is true in this context
    };
    
    onXSave = event => {
      const obj = { x: ref.current}; // by using ref, the value is always current
      };
    }

    【讨论】:

    • 所以正确的方法是每次x状态发生变化时向useEffect中依赖x的按钮添加一个新的eventListener?
    • @Matt 你可以使用ref
    • 这很重要,因为它已经关闭了 x 的原始值
    【解决方案2】:

    您添加到eventListeneronXSave 版本已过期 - 您仅在第一次渲染时添加一次,因此当x 更新并导致重新渲染时,您的 useEffect 不会'不要再次运行,您的 jQueryButton 仍将保留原始功能,该功能已关闭了过期版本的 x

    你需要做两件事:

    1. useEffect 依赖数组中添加 onXSavejQueryButton 作为依赖项(因此当它重新渲染时,函数的当前版本会连接到 eventListener)
    2. 通过从您的 useEffect 返回一个清理函数来删除重新渲染时的旧事件侦听器。

    比如:

    function MyComponent(props) {
       const [x, setX] = useState(false);
    
    // On initial render
    useEffect(() => {
       props.jQueryButton.addEventListener('click', onXSave)
       return ()=> props.jQueryButton.removeEventListener('click', onXSave)
    }, [onXSave, props.jQueryButton])
    
    useEffect(() => {
        console.log("x changed " + x); // everytime onXChange is called, x 
        state is updated with the checked value, and this console.log shows 
        the correct state value
    }, [x]);
    
    onXChange = event => {
       setX(event.target.checked); // checked is true in this context
    };
    
    onXSave = event => {
      const obj = { x: x}; // x is false here, even though the state in this context shows it to be true.
      };
    
    
    }
    

    【讨论】:

      猜你喜欢
      • 2020-11-30
      • 1970-01-01
      • 2021-10-02
      • 2020-05-19
      • 1970-01-01
      • 1970-01-01
      • 2020-04-19
      • 2022-01-21
      • 2021-10-23
      相关资源
      最近更新 更多