reactjs - useEffect 模拟 componentWillUnmount 不返回更新状态

标签 reactjs react-hooks use-effect

我有一个功能组件,它使用 useState 初始化状态,然后通过输入字段更改此状态。

然后,我有一个 useEffect Hook 来模拟 componentWillUnmount,以便在组件卸载之前,将当前更新的状态记录到控制台。但是,会记录初始状态而不是当前状态。

这是我想要做的事情的简单表示(这不是我的实际组件):

import React, { useEffect, useState } from 'react';

const Input = () => {
    const [text, setText] = useState('aaa');

    useEffect(() => {
        return () => {
            console.log(text);
        }
    }, [])

    const onChange = (e) => {
        setText(e.target.value);
    };

    return (
        <div>
            <input type="text" value={text} onChange={onChange} />
        </div>
    )
}

export default Input;

我将状态初始化为“初始”。然后我使用输入字段来更改状态,假设我输入“新文本”。但是,当组件卸载时,控制台将记录“初始”而不是“新文本”。

为什么会发生这种情况?如何在卸载时访问当前更新的状态?

非常感谢!

编辑:

向 useEffect 依赖项数组添加文本并不能解决我的问题,因为在我的现实场景中,我想要做的是根据当前状态触发异步操作,但这样做效率不高每次“文本”状态发生变化时。

我正在寻找一种方法,仅在组件卸载之前获取当前状态。

最佳答案

您已经有效地记住了初始状态值,因此当组件卸载时,该值就是返回函数包含在其范围内的值。

Cleaning up an effect

The clean-up function runs before the component is removed from the UI to prevent memory leaks. Additionally, if a component renders multiple times (as they typically do), the previous effect is cleaned up before executing the next effect. In our example, this means a new subscription is created on every update. To avoid firing an effect on every update, refer to the next section.

为了在调用清理函数时获取最新状态,您需要在依赖项数组中包含 text 以便更新函数。

Effect hook docs

If you pass an empty array ([]), the props and state inside the effect will always have their initial values. While passing [] as the second argument is closer to the familiar componentDidMount and componentWillUnmount mental model, there are usually better solutions to avoid re-running effects too often.

这意味着返回的“清理”函数仍然只访问前一个渲染周期的状态和 Prop 。

编辑

useRef

useRef returns a mutable ref object whose .current property is initialized to the passed argument (initialValue). The returned object will persist for the full lifetime of the component.

...

It’s handy for keeping any mutable value around similar to how you’d use instance fields in classes.

使用引用将允许您缓存可在清理函数中访问的当前文本引用。

/编辑

组件

import React, { useEffect, useRef, useState } from 'react';

const Input = () => {
  const [text, setText] = useState('aaa');

  // #1 ref to cache current text value
  const textRef = useRef(null);
  // #2 cache current text value
  textRef.current = text;

  useEffect(() => {
    console.log("Mounted", text);

    // #3 access ref to get current text value in cleanup
    return () => console.log("Unmounted", text, "textRef", textRef.current);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  useEffect(() => {
    console.log("current text", text);
    return () => {
      console.log("previous text", text);
    }
  }, [text])

  const onChange = (e) => {
    setText(e.target.value);
  };

  return (
    <div>
      <input type="text" value={text} onChange={onChange} />
    </div>
  )
}

export default Input;

通过返回的清理函数中的 console.log,您会注意到输入中的每次更改都会将之前的状态记录到控制台。

Edit zen-leftpad-twogm

在此演示中,我记录了效果中的当前状态清理函数中的先前状态。请注意,清理函数首先在下一个渲染周期的当前日志之前记录。

关于reactjs - useEffect 模拟 componentWillUnmount 不返回更新状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60734531/

相关文章:

javascript - 在组件的单​​独文件中使用 React hook

arrays - 使用 React 钩子(Hook),我如何更新通过 Prop 传递给 child 的对象?

javascript - 如何将 setTimeout() 与 React Hooks useEffect 和 setState 一起使用?

javascript - 将 .map() 与 useEffect 和 Api 一起使用

javascript - 使用 React.JS 选择 - 动态填充选项

javascript - React TypeScript 和 ForwardRef - 类型 'IntrinsicAttributes 上不存在属性 'ref'

javascript - 错误: React Hook "useRouter" - nextJs/javascript app not building

javascript - React 中状态变量的顺序重要吗?

reactjs - 尝试导入错误: 'Wallet' is not exported from '@project-serum/anchor'

reactjs - 期望在 react 测试库中使用参数调用 jest mock 失败