React使用useEffect解决setState副作用详解

 更新时间:2022年10月26日 16:37:01   作者:heheer  
这篇文章主要为大家介绍了React使用useEffect解决setState副作用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

介绍一下API

本文主要内容:描述了setState与fetch之间产生的冲突副作用,并使用useEffect进行解决

API,即Application Programming Interface,应用程序接口,是很多程序向开发人员提供的易于使用的抽象化的代码。

比如经常会用到的查询天气API,智能识图API,如果是直接照着复杂的代码编写,会相当不友好。而API则只需按照它们提供的规则即可简单、方便、安全地使用。

fetch()方法访问API

我们会用到一个很简单的资源API,https://swapi.dev/api/people/1,这是一个会返回星球大战里的人物信息的API。

所以我们要做的事:1、读取API中提供的数据; 2、将获得的数据写入state。

首先我们来做第一步,这里介绍一下fetch()

fetch() 必须接受一个参数——资源的路径。无论请求成功与否,它都返回一个 Promise 对象,resolve 对应请求的Response。

一旦 Response被返回,就可以使用一些方法来定义内容的形式

所以我们可以使用以下代码完成资源API的读取,并且渲染到页面上

import React from "react"
export default function App() {
    const [starWarsData, setStarWarsData] = React.useState({})
    fetch("https://swapi.dev/api/people/1")
        .then(res => res.json())
        .then(data => setStarWarsData(data))
    return (
        <div>
            <pre>{JSON.stringify(starWarsData, null, 2)}</pre>
        </div>
    )
}

可以看到我们似乎确实轻松地获得了资源接口所提供给我们的数据

然而当我们加上控制台的输出后,事情就变得不一样了

setState的副作用

在这个程序中,我们可以加上一句console.log在控制台输出后天的运行情况,如下

import React from "react"
export default function App() {
    const [starWarsData, setStarWarsData] = React.useState({})
    console.log("component rendered")
    fetch("https://swapi.dev/api/people/1")
        .then(res => res.json())
        .then(data => setStarWarsData(data))
    return (
        <div>
            <pre>{JSON.stringify(starWarsData, null, 2)}</pre>
        </div>
    )
}

这时再运行就能清楚地看到在控制台处显示了这个组件在一直不断地生成,重新地render

我们可以简单地分析一下原因,

  • 组件每次render都会触发一次fetch,
  • 然后fetch获取的数据传入setState又会重新使得组件被render一遍,

而这就形成了一个死循环,致使组件不断地生成。

使用useEffect解决这个问题

useEffect()出现之前,react并没有setState后停止render的方法,这就使得setState的使用需要非常谨慎,不过如今提供了useEffet()来解决这个问题

useEffect接受两个参数,其中第二个参数是可选的

useEffect(<function>, <dependency array>)

所以让我们先来尝试一下不使用第二个参数会得到什么结果

import React from "react"
export default function App() {
    const [starWarsData, setStarWarsData] = React.useState({})
    console.log("component rendered")
    React.useEffect(function(){
        fetch("https://swapi.dev/api/people/1")
            .then(res => res.json())
            .then(data => setStarWarsData(data))
    })
    return (
        <div>
            <pre>{JSON.stringify(starWarsData, null, 2)}</pre>
        </div>
    )
}

可以看到在上面的代码里我们已经按照语法要求使用了useEffect(),然而结果却不如我们所设想的只打印一条语句,依旧是一个死循环

原因在于只使用一个参数的useEffect()的效果是在组件被挂载被更新两种情况下执行参数的函数,所以并不能解决更新状态不执行的效果

那么就要用到第二个参数了,第二个参数叫做dependency array,只有在这个数组里的元素更新了,才会触发这个useEffect

所以这里我们可以将第二个参数设置为一个空数组,这样只有在组件刚刚被挂载的时候才会执行useEffect,很好的解决了我们只需要读取一遍API的任务要求

import React from "react"
export default function App() {
    const [starWarsData, setStarWarsData] = React.useState({})
    console.log("component rendered")
    React.useEffect(function(){
        fetch("https://swapi.dev/api/people/1")
            .then(res => res.json())
            .then(data => setStarWarsData(data))
    }, [])
    return (
        <div>
            <pre>{JSON.stringify(starWarsData, null, 2)}</pre>
        </div>
    )
}

使用useEffect操控函数运行

dependency array我们也可以得出另一种用法,可以看以下代码

import React from "react"
export default function App() {
    const [count, setCount] = React.useState(0)
    console.log("Component rendered")
    React.useEffect(() => {
        console.log("Effect function ran")
    }, [count])
    return (
        <div>
            <h2>The count is {count}</h2>
            <button onClick={() => setCount(prevCount => prevCount + 1)}>Add</button>
        </div>
    )
}

我们在第二个参数处填入了会随着我们点击而变化的count,所以在我们每次点击使得count增加以后,count state发生变化,执行useEffect第一个参数的函数

可以看到设置了count state,再在useEffect中设置countdependency,这样每次改变count的值就会再一次执行useEffect中的函数。

以上就是React使用useEffect解决setState副作用详解的详细内容,更多关于React useEffect解决setState的资料请关注脚本之家其它相关文章!

相关文章

  • React 使用recharts实现散点地图的示例代码

    React 使用recharts实现散点地图的示例代码

    这篇文章主要介绍了React 使用recharts实现散点地图的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-12-12
  • 深入理解React 三大核心属性

    深入理解React 三大核心属性

    本文主要介绍了React 三大核心属性,主要包括State属性,Props属性,Refs属性,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-02-02
  • ahooks解决用户多次提交方法示例

    ahooks解决用户多次提交方法示例

    这篇文章主要为大家介绍了ahooks解决用户多次提交的方法示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07
  • JavaScript的React框架中的JSX语法学习入门教程

    JavaScript的React框架中的JSX语法学习入门教程

    这篇文章主要介绍了JavaScript的React框架中的JSX语法学习入门教程,React是由Facebook开发并开源的高人气js框架,需要的朋友可以参考下
    2016-03-03
  • React如何配置src根目录@

    React如何配置src根目录@

    这篇文章主要介绍了React如何配置src根目录@,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2024-01-01
  • React Native验证码倒计时工具类分享

    React Native验证码倒计时工具类分享

    这篇文章主要为大家分享了React Native验证码倒计时工具类,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-10-10
  • 使用react-beautiful-dnd实现列表间拖拽踩坑

    使用react-beautiful-dnd实现列表间拖拽踩坑

    相比于react-dnd,react-beautiful-dnd更适用于列表之间拖拽的场景,本文主要介绍了使用react-beautiful-dnd实现列表间拖拽踩坑,感兴趣的可以了解一下
    2021-05-05
  • jsoneditor二次封装实时预览json编辑器组件react版

    jsoneditor二次封装实时预览json编辑器组件react版

    这篇文章主要为大家介绍了jsoneditor二次封装实时预览json编辑器组件react版示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-10-10
  • react PropTypes校验传递的值操作示例

    react PropTypes校验传递的值操作示例

    这篇文章主要介绍了react PropTypes校验传递的值操作,结合实例形式分析了react PropTypes针对传递的值进行校验操作相关实现技巧,需要的朋友可以参考下
    2020-04-04
  • react-router4 配合webpack require.ensure 实现异步加载的示例

    react-router4 配合webpack require.ensure 实现异步加载的示例

    本篇文章主要介绍了react-router4 配合webpack require.ensure 实现异步加载的示例,非常具有实用价值,需要的朋友可以参考下
    2018-01-01

最新评论