useEffect 模拟 componentWillUnmount 不返回更新状态

2023-11-29

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

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

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

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;

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

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

非常感谢!

Edit:

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

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


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

清理效果

清理函数在组件从 UI 中删除之前运行 以防止内存泄漏。此外,如果一个组件呈现多个 次(正如他们通常所做的那样),之前的效果已被清除 执行下一个效果。在我们的例子中,这意味着一个新的 每次更新时都会创建订阅。为了避免触发效果 每次更新,请参阅下一节。

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

效果挂钩文档

如果您传递一个空数组([]), the 效果内的 props 和 state 总是有它们的初始值。路过时[]作为第二个 论证更接近熟悉的componentDidMount and componentWillUnmount心智模型,通常有更好的解决方案 以避免过于频繁地重新运行效果。

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

EDIT

useRef

useRef返回一个可变的 ref 对象,其.current财产是 初始化为传递的参数(initialValue)。返回的对象 将在组件的整个生命周期中持续存在。

...

It’s 方便保存任何可变值类似于在类中使用实例字段的方式。

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

/EDIT

成分

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

useEffect 模拟 componentWillUnmount 不返回更新状态 的相关文章

随机推荐

  • 如何在另一种方法中使用一种方法的“返回”值

    我目前正在开发这个玩高低骰子游戏的项目 我被困在如何使用返回的char from getHighLow和返回的int from getBet and getRoll in determineWinnings 这是我目前学习 Java 的第一
  • 如何在软件中模拟浮点运算? [关闭]

    Closed 这个问题需要多问focused 目前不接受答案 当CPU没有 或有问题 浮点单元时 软件如何执行浮点运算 例如 PIC AVR 和 8051 微控制器架构 效仿 在 PIC AVR 和 8051 上下文中 浮点 是错误的术语
  • 确保字符串文字联合属于对象的键

    export type A a b c const obj a 4 b 5 c 6 d 7 我如何确保所有元素A是对象的键obj 根据您的需要 您可以自动构造您的类型 所有键作为一个类型 您可以使用keyof将所有密钥作为一个联合体 自从k
  • 如何根据 Javascript 中的多个键对对象数组进行分组?

    我的数组如下 WarehouseId 1 ShippingCarrierId 1 PostalCodeType ShipToCustomer TimeStart 1970 01 01T06 00 00 000Z TimeEnd 1970 0
  • 使用 jQuery AJAX 发送带有二进制数据的 FormData

    我想发送一个FormData通过使用 jQuery AJAX 例如 var uploadFormData new FormData uploadFormData append name value ajax url URL target t
  • 当我返回时,控制到达非空函数的末尾[重复]

    这个问题在这里已经有答案了 我有一个函数 它递归地调用自身 直到连接到服务器 然后函数返回0 为什么我有这样的错误行为 控制到达非空函数的末尾 指向函数结束的行 我做错了什么 我有 if else 语句 仅在 else 中返回 但即使在 i
  • 为什么 Rust 允许在一个作用域中两次声明相同的变量名? [复制]

    这个问题在这里已经有答案了 我第一次遇到允许在同一范围内声明变量名称两次的类型化语言 难道不会有机会错误地覆盖现有变量吗 它带来什么优势 有书中有一章介绍了这一点 隐藏与将变量标记为 mut 不同 因为如果我们不小心尝试在不使用 let 关
  • 从公共方法调用私有方法?

    我定义了一个这样的类 function Class1 this Func1 function Methods and vars function Func2 Methods and vars 我想找到一种从私有方法 Func2 调用公共方法
  • 在 vbscript 中使用 HTA

    在使用 VBscript 的 HTA 用户窗体时 我发现 HTA 不支持 WScript 及其对象 方法 是否有其他创建用户表单的方法 或者有什么方法可以使 HTA 支持 WScript 替代方案WScript Echo就是简单地将内容添加
  • 如何在 Openmodelica 中指定介质?

    我正在 Modelica 中模拟热泵热水系统 我附上了我的模特的照片 但是 当我运行模型时 出现错误 Medium 是部分的 部分类中不允许进行名称查找 您能告诉我吗 我该如何指定水箱 热泵冷凝器和管道中的水 我应该如何指定热泵蒸发器中的空
  • 使用包含通配符条件的数组时出现问题

    我一直在尝试运行 powershell 代码将文件分成 2 个 我有几个常规数组 效果很好 第三个数组包含每个条件的通配符 但这根本不起作用 我尝试过 in notin like notlike contains notcontains m
  • 如何最大程度地划分集合?

    我正在尝试解决欧拉计划问题之一 因此 我需要一种算法来帮助我以任意顺序找到集合中所有可能的分区 例如 给定集合2 3 3 5 2 3 3 5 2 3 3 5 2 3 3 5 2 3 3 5 2 5 3 3 等等 几乎该组成员的所有可能组合
  • MPMoviePlayer 控制风格

    我想使用以下代码隐藏 MPMoviePlayer 中的控件 IBAction video id sender NSBundle bundle NSBundle mainBundle NSString moviePath bundle pat
  • 如何在宏中获取当前命名空间的字符串

    我需要在宏中添加名称空间前缀 IE define MYMACRO x x namespace A namespace B MYMACRO C 并且 MYMACRO 必须返回 A B C 无法工作 命名空间由编译器识别 编译器仅在预处理器之后
  • 设置图像属性时,UIImageView 图像不会明显更新

    我有一个 UIImageView 其用户交互是真实的 并且我为其提供了点击手势识别器 其操作处理程序如下 IBAction func tap sender UITapGestureRecognizer let iv sender view
  • 如何使用 browsermob-proxy 修复“地址已在使用中”错误?

    我还在尝试使用browsermob proxy here 尝试在 python selenium 测试期间监控网络流量 请参阅browsermob代理 我正在使用以下脚本来测试它 from browsermobproxy import Se
  • 如何解码众多 Decodable Swift 中的单个异常属性?

    我有一个符合 Decodable 的结构 它有 50 个 String 属性 只有 1 个 Bool 属性 该布尔值来自服务器 如字符串 false true 或有时如整数 0 1 因此无法从框中解码 我怎样才能让它解码而不是对所有 50
  • 每行最后一个非 NA 行的列名称;使用 tidyverse 解决方案?

    数据集简要描述 我有从 Qualtrics 生成的调查数据 我已将其作为 tibble 导入到 R 中 每列对应一个调查问题 并且我保留了原始列顺序 以与调查中问题的顺序相对应 用通俗易懂的语言描述问题 由于参与者的正常流失 并非所有参与者
  • 无法启动/private/var/containers/Bundle/Application/

    我一直在尝试在 iOS 12 设备上测试应用程序 但每次构建它时 它都会在设备 我的 iPhone 或 iPad 上成功构建 但会崩溃 并且我收到以下消息 无法启动 private var containers Bundle Applica
  • useEffect 模拟 componentWillUnmount 不返回更新状态

    我有一个使用 useState 初始化状态的功能组件 然后通过输入字段更改该状态 然后 我有一个模拟 componentWillUnmount 的 useEffect 挂钩 以便在组件卸载之前 将当前更新的状态记录到控制台 但是 会记录初始