正文从这开始~

总览

为了解决"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. CentOS6安装PLEX

    CentOS6安装PLEX 一.安装使用PLEX 1.1 安装 1)下载 https://www.plex.tv/downloads/ plexmediaserver-1.11.3.4803-c40b ...

  2. 【JNPF修改通告】fastjson≤1.2.80反序列化漏洞

    近日Fastjson Develop Team 发现 fastjson 1.2.80及以下存在新的风险,存在反序列化漏洞.攻击者可绕过默认autoType关闭限制,攻击远程服务器,风险影响较大,请大家 ...

  3. Typecho博客转移服务器,数据备份.

    目录 Typecho博客转移服务器,数据备份. 简述操作(有基础的mjj看这个简述就可以了.) 详细步骤(建议小白来看, 已经在很多详细方面进行说明了.) 备份篇 备份导入与数据库转移篇 重新部署ty ...

  4. SQL Server之自动创建视图

    本方法只适合特定模式的视图创建. 比如,创建需要整张表列名的视图,或者当表和需要的列名统计在一张数据表当中,如图所示: 首先要先获取要创建视图所需要的表,这里我获取的是整个数据库中的表, IF OBJ ...

  5. GDKOI 2021 Day1 PJ 爆炸记

    早上睡到 7:10 分才想起今天有 GDKOI ,赶紧去买了一个面包赶去机房 发现隔壁的大奆都过来了.比赛时由于昨晚一直没睡好,打了两个小时的哈欠 T1 :暴力模拟 根据 \(r\) 和 \(c\) ...

  6. Spring框架系列(4) - 深入浅出Spring核心之面向切面编程(AOP)

    在Spring基础 - Spring简单例子引入Spring的核心中向你展示了AOP的基础含义,同时以此发散了一些AOP相关知识点; 本节将在此基础上进一步解读AOP的含义以及AOP的使用方式.@pd ...

  7. 关于swiper插件在vue2的使用

    最近做项目用到了vue-awesome-swiper,总结一下使用方法 第一步:安装依赖 npm install swiper vue-awesome-swiper --save or npm ins ...

  8. idea 查看 类所有方法的快捷键

    idea 查看 类 所有方法的快捷键 Idea:ctrl+F12 Eclipse:Ctrl+O

  9. 一文详解|Go 分布式链路追踪实现原理

    在分布式.微服务架构下,应用一个请求往往贯穿多个分布式服务,这给应用的故障排查.性能优化带来新的挑战.分布式链路追踪作为解决分布式应用可观测问题的重要技术,愈发成为分布式应用不可缺少的基础设施.本文将 ...

  10. Linux YUM制作自己的yum repository

    Linux YUM制作自己的yum repository 配置步骤: 1.通过网络发布自己的package目录 2.创建本地repository 3.配置自己的yum源 操作实现: 1 安装creat ...