解决react中useState状态异步更新的问题

目录
  • 疑惑
  • 状态异步更新带来的问题
  • 问题示例
  • 问题解决
    • 类组件的解决方案
    • 函数组件的解决方案
  • 其他解决方案
  • 结尾

疑惑

相信刚开始使用react函数组件的小伙伴也遇到过一个坑,就是 useState 更新状态是异步更新的,但是react 并没有提供关于这个问题的解决方案。那我们能否使用自己的方法来解决这个问题呢?答案肯定是可以的。

状态异步更新带来的问题

就拿一个比较常见的场景来说。在react项目中,我们想在关闭对话框后再去处理其他业务。但是 useState 的状态是异步更新的。我们通过setVisible 更新状态后,状态并没有立马更新,这也就说明对话框并没有关闭,这也就造成了我们后面的逻辑在对话框没关闭时就执行了,这并不是我们想要的结果。下面来看我是如何来巧妙的解决这个问题的。

问题示例

// App.tsx
import {useState} from "react"

export default ()=>{

const [num,setNum]=useState(0)

const add=()=>{
  console.log("更新前",num)
  setNum(num+1)
  console.log('更新后',num)
}

return(
<div className='App'>
 <p>{num}</p>
 <button onClick={add}>num++</button>
</div>
)
}

下面是上面组件运行结果:

点击按钮后的运行结果:

当我们点击按钮时的打印结果:

问题解决

类组件的解决方案

在类组件中,我们可以在 setState(newstate,callback) 第二个参数传一个回调来处理本次状态更新后的一些其他业务。但是在函数组件中我们如何来解决这个问题呢?来看以下方案,也是我们这篇文章主要想为大家解决的问题。

函数组件的解决方案

解决该问题使用到的 api有:useEffectPromise

1.在项目源码目录下创建文件夹 customHooks,然后在 customHooks/useCallbackState.ts中编写如下代码:

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

export default(initState: any)=>{
    const stateRef = useRef(null as any);
    const [state, setState] = useState(initState);

    useEffect(() => {
    stateRef.current && stateRef.current(state);
    }, [state]);

    return [
        state,
        (newState:typeof initState):Promise<typeof initState>=>
        new Promise(rel=>{stateRef.current=rel;setState(newState)})
    ];
}

2.在上面的 App.tsx中使用上面的自定义hook

import useCallbackState from "@/customHooks/useCallbackState"
const [num,setNum]=useCallbackState(0)

const add=()=>{
   console.log('更新前',num)
   setNum(num+1)
   .then((newNum:any)=>{
   console.log('更新后',newNum)
   // console.log(num)
  })
}

此时的运行结果如下:

注意:谨慎使用,打印可以看出,其实状态并没有真正完成更新。依然达不到类组件callback的效果。

其他解决方案

如果真的存在上面这种需求,我们可以使用类组件,或者使用 setTimeout来解决上面的问题,把对话框关闭后的业务写在延时的回调中就行了,延时个 500 毫秒 状态一定更新完毕了,个人感觉这个方法不太好,还是推荐使用类组件来解决上述问题。

结尾

到此这篇关于解决react中useState状态异步更新的问题的文章就介绍到这了,更多相关react useState状态异步更新内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 示例详解react中useState的用法

    useState useState 通过在函数组件里调用它来给组件添加一些内部 state.React 会在重复渲染时保留这个 state.useState 会返回一对值:当前状态和一个让你更新它的函数,你可以在事件处理函数中或其他一些地方调用这个函数.它类似 class 组件的 this.setState,但是它不会把新的 state 和旧的 state 进行合并. 接下来通过一个示例来看看怎么使用 useState. 有这么一个需求:需要在 iframe 中加载外部网页. 初始的代码我们通过

  • 解决react中useState状态异步更新的问题

    目录 疑惑 状态异步更新带来的问题 问题示例 问题解决 类组件的解决方案 函数组件的解决方案 其他解决方案 结尾 疑惑 相信刚开始使用react函数组件的小伙伴也遇到过一个坑,就是 useState 更新状态是异步更新的,但是react 并没有提供关于这个问题的解决方案.那我们能否使用自己的方法来解决这个问题呢?答案肯定是可以的. 状态异步更新带来的问题 就拿一个比较常见的场景来说.在react项目中,我们想在关闭对话框后再去处理其他业务.但是 useState 的状态是异步更新的.我们通过se

  • 解决React中的re-render问题

    目录 re-render? 错误的优化 Object.is 合理使用useEffect,解决re-render 简单实现useEffect 文章转自公众号:前端巅峰 re-render? 首先使用我的脚手架: npm i ykj-cli -g  ykj init App cd ./app yarn  yarn dev 这样一个webpack5.TS.React项目就搭建好了 我们目前只有一个APP组件,内部代码: import Myy from './myy.jpg'; function App

  • React中useState的使用方法及注意事项

    目录 一.基本使用 第一个问题:setCount修改值时它是同步还是异步? 第二个问题:连续调用 setCount会发生什么? 二.注意事项 1.复杂变量的修改 2.异步操作获取更新的值 总结 一.基本使用 useState是 react 提供的一个定义响应式变量的 hook 函数,基本语法如下: const [count, setCount] = useState(initialCount) 它返回一个状态和一个修改状态的方法,状态需要通过这个方法来进行修改: initialCount 是我们

  • 解决React hook 'useState' cannot be called in a class component报错

    目录 总览 函数组件 类组件中使用setState() 总览 当我们尝试在类组件中使用useState 钩子时,会产生"React hook 'useState' cannot be called in a class component"错误.为了解决该错误,请将类组件转换为函数组件.因为钩子不能在类组件中使用. 这里有个例子用来展示错误是如何发生的. // App.js import {useState, useEffect} from 'react'; class Example

  • React中setState同步异步场景的使用

    目录 setState同步异步场景 描述 原理 保证内部数据统一 启用并发更新 参考 setState同步异步场景 React通过this.state来访问state,通过this.setState()方法来更新state,当this.setState()方法被调用的时候,React会重新调用render方法来重新渲染UI.相比较于在使用Hooks完成组件下所需要的心智负担,setState就是在使用class完成组件下所需要的心智负担,当然所谓的心智负担也许叫做所必须的基础知识更加合适一些.

  • React 中state与props更新深入解析

    目录 正文 组件的 updater 处理 ClickCounter Fiber 的 update beginWork Reconciling children for the ClickCounter Fiber 处理 Span Fiber 的 update Reconciling children for the span fiber Effects list commit 阶段 应用 effects DOM updates 调用 Post-mutation 生命周期 正文 在这篇文章中,我使

  • 解决vue中数据更新视图不更新问题this.$set()方法

    目录 vue数据更新视图不更新 解决问题 vue数据不更新的原因(数据更改了,但是视图没有更新) 解决办法 具体流程如下 数组更新检测 注意事项 对象更改检测注意事项 vue数据更新视图不更新 1.data中有对象obj :{name:'远航',age:18} 2.此时新增phone this.obj.phone = '123456' 再次更新 用this.obj.phone = '654321' 视图未更新  用this.$set(this.obj,"phone", "65

  • 解决ASP中http状态跳转返回错误页的问题

    IIS默认的错误页是很不友好的,很多人看到默认的错误页时都会说:网站打不开了!白白损失了这部分流量.而如果错误页直接跳转到首页又对搜索引擎很不友好,搞不好首页还会被封掉.所以根据情况,有两个方法解决这个问题: 如果是博客等内容型的网站,可以返回一个带有404错误的搜索框让访客搜索,若是电子商务型网站,则可以返回一个带有404错误的进度条进行跳转.这两种方法即照顾了访客又顾及到了SEO. 可以在Google webmaster tools中查看自己网站错误页有多少. 修改默认错误页的方法很简单:在

  • 解决react中label标签for报错问题

    要求:点击账号或密码,自动将焦点转到相关的表单控件(input)上. 问题:功能可以使用,但是会有报错. 解决办法:react中label标签没有for属性,用htmlFor代替for属性 demo的代码: 报错 修改后的代码 到此这篇关于react中label标签for报错的文章就介绍到这了,更多相关react中label标签内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

随机推荐