正文从这开始~

总览

为了解决"Warning: Can't perform a React state update on an unmounted component" ,可以在你的useEffect钩子中声明一个isMounted布尔值,用来跟踪组件是否被安装。一个组件的状态只有在该组件被挂载时才会被更新。

import {useState, useEffect} from 'react';

const App = () => {
const [state, setState] = useState(''); useEffect(() => {
// ️ set isMounted to true
let isMounted = true; async function fetchData() {
const result = await Promise.resolve(['hello', 'world']); // ️ only update state if component is mounted
if (isMounted) {
setState(result);
}
} fetchData(); return () => {
// ️ when component unmounts, set isMounted to false
isMounted = false;
};
}, []); return (
<div>
<h2>State: {JSON.stringify(state)}</h2>
</div>
);
}; export default App;

当我们试图更新一个未挂载的组件的状态时,会出现"无法在未挂载的组件上执行React状态更新"的警告。

isMounted

摆脱该警告的直截了当的方式是,在useEffect钩子中使用isMounted布尔值来跟踪组件是否被挂载。

useEffect中,我们初始化isMounted布尔值为true

我们的fetchData 函数执行一些异步的任务,最常见的是一个API请求,并根据响应来更新状态。

然而,需要注意的是,我们只有当isMounted变量被设置为true时,才会更新状态。

async function fetchData() {
const result = await Promise.resolve(['hello', 'world']); // ️ only update state if component is mounted
if (isMounted) {
setState(result);
}
}

这可以帮助我们避免警告,因为如果组件没有挂载,我们就不会更新状态。

当组件卸载时,从useEffect钩子返回的函数会被调用。

return () => {
// ️ when component unmounts, set isMounted to false
isMounted = false;
};

我们设置isMounted变量为false,表示该组件不再挂载。如果fetchData函数在组件卸载时被调用,if代码块不会执行是因为isMounted设置为false

async function fetchData() {
const result = await Promise.resolve(['hello', 'world']); // ️ only update state if component is mounted
if (isMounted) {
setState(result);
}
}

提取

如果经常这样做,可以将逻辑提取到可重用的钩子中。

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

// ️ extract logic into reusable hook
function useIsMounted() {
const isMounted = useRef(false); useEffect(() => {
isMounted.current = true; return () => {
isMounted.current = false;
};
}); return isMounted;
} const App = () => {
const [state, setState] = useState(''); // ️ use hook
const isMountedRef = useIsMounted(); useEffect(() => {
async function fetchData() {
const result = await Promise.resolve(['hello', 'world']); // ️ only update state if component is mounted
if (isMountedRef.current) {
setState(result);
}
} fetchData();
}, [isMountedRef]); return (
<div>
<h2>State: {JSON.stringify(state)}</h2>
</div>
);
}; export default App;

useRef()钩子可以传递一个初始值作为参数。该钩子返回一个可变的ref对象,其.current属性被初始化为传递的参数。

我们在useIsMounted钩子中跟踪组件是否被挂载,就像我们直接在组件的useEffect钩子中做的那样。

需要注意的是,在fetchData函数中,我们必须检查isMountedRef.current 的值,因为ref上的current属性是ref的实际值。

React报错之无法在未挂载的组件上执行React状态更新的更多相关文章

  1. VM中装Linux换ISO文件报错"该光盘无法被挂载"

    一.发现问题 利用VM安装Red Hat Linux的时候,第一个iso安装完毕,准备换第二个iso,报错“该光盘无法被挂载”. 二.解决办法 上面的菜单栏中“虚拟机”—>“设置”—>“硬 ...

  2. Oracle添加记录的时候报错:违反完整性约束,未找到父项关键字

    今天需要向一个没有接触过的一个Oracle数据库中添加一条记录,执行报错: 分析: 报错的根本原因:未找到父项关键字的原因是因为你在保存对象的时候缺失关联对象. 问题的解决思路:先保存关联对象后再保存 ...

  3. react 报错的堆栈处理

    react报错 Warning: You cannot PUSH the same path using hash history 在Link上使用replace 原文地址https://reactt ...

  4. [转]ORACLE 11G 导出报错(EXP-00003)未找到段 (0,0) 的存储定义

    http://blog.csdn.net/qq_19524879/article/details/51313205 ORACLE 11G 导出报错(EXP-00003)未找到段 (0,0) 的存储定义 ...

  5. 解决Oracle+Mybatis批量插入报错:SQL 命令未正确结束

    Mybatis批量插入需要foreach元素.foreach元素有以下主要属性: (1)item:集合中每一个元素进行迭代时的别名. (2)index:指定一个名字,用于表示在迭代过程中,每次迭代到的 ...

  6. 报错:该字符串未被识别为有效的DateTime

    报错:该字符串未被识别为有效的DateTime □ 背景 前端的搜索条件中包含关于时间的字符串,由jquery ui的datepicker产生时间字符串. 服务端对时间做了一次转换:DateTime. ...

  7. 小程序报错:出现脚本错误或者未正确调用 Page()的解决办法

    场景是两个人共同开发小程序,我使用的是pc端,另一个同事是用的mac端,我这边能够正常运行项目,代码提交到git,同事check下来发现运行报错: 出现脚本错误或者未正确调用 Page(); 如图 一 ...

  8. React报错之Cannot find namespace context

    正文从这开始~ 总览 在React中,为了解决"Cannot find namespace context"错误,在你使用JSX的文件中使用.tsx扩展名,在你的tsconfig. ...

  9. angularjs 遇见$scope,xxx=function()报错为该函数未定义

    本包子今天遇见一个问题,就是明明写了$scope,xx=function()但是报错了,报错显示是该函数未定义,我就很着急的先将函数写成一个全局函数,就没问题,等下午有空的时候寻思了一下,为什么全局就 ...

随机推荐

  1. 【多线程】线程同步 synchronized

    由于同一进程的多个线程共享同一块存储空间 , 在带来方便的同时,也带来了访问 冲突问题 , 为了保证数据在方法中被访问时的正确性 , 在访问时加入 锁机制synchronized , 当一个线程获得对 ...

  2. python之装饰器补充与递归函数与二分查找

    目录 多层装饰器 有参装饰器 递归函数 基本演示 斐波那契数列 总结 小拓展 算法之二分法 简介 举例 总结 多层装饰器 我们已经知道了语法糖的作用是将装饰对象自动装饰到装饰器中,一个语法糖的应用我们 ...

  3. HTML行内元素与块级元素有哪些及区别详解

    转自 https://www.jb51.net/web/724286.html   这篇文章主要介绍了HTML行内元素与块级元素有哪些及区别详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具 ...

  4. anaconda遇到:Solving environment: failed with initial frozen solve. Retrying with flexible solve.问题

    Solving environment: failed with initial frozen solve. Retrying with flexible solve. 遇到上述问题: 解决方案: # ...

  5. UVA471 Magic Numbers 题解

    1.题目 题意很简单:输入n,枚举所有的a,b,使得 (1)满足a/b=n. (2)满足a,b各个位上的数字不相同. 2.思路 (1)对于被除数,要满足各个位上的数字,显然最大枚举到987654321 ...

  6. 【物联网串口服务器通信经验教程】Modbus网关协议转换

    在前面的文章中,我们已经详细地介绍了Modbus网关的几种主要类型,今天,就让我们来介绍一下其中简单协议转换的处理过程. 简单协议转换是最常规.最普遍的Modbus网关功能,也是数据处理效率最高Mod ...

  7. AsList()方法详解

    AsList()方法详解 在Java中,我们应该如何将一个数组array转换为一个List列表并赋初始值?首先想到的肯定是利用List自带的add()方法,先new一个List对象,再使用add()方 ...

  8. tmux(Terminal MultipleXer)命令使用

    作用:命令行多窗口显示:命令行程序与本机脱离 1 安装tmux (1)redhat.centos系统 yum install tmux (2)ubuntu系统 apt-get install tmux ...

  9. iOS全埋点解决方案-APP和H5打通

    前言 ​ 所谓的 APP 和 H5 打通,是指 H5 集成 JavaScript 数据采集 SDK 后,H5 触发的事件不直接同步给服务器,而是先发给 APP 端的数据采集 SDK,经过 APP 端数 ...

  10. 记安装AWVS14过程踩的坑

    由于之前的AWVS14用着用着无法扫描了,一扫就是失败,一气之下就重装系统了.重装系统后发现安装还是不行,折腾了好久,终于找到方法了. 安装acunetix_14.1.210324124.exe 没啥 ...