React ----- useEffected

本文详细介绍了React中的useEffect钩子,包括纯函数概念、副作用处理、依赖项控制、清理操作、useLayoutEffect与useInsertionEffect的区别,以及在实际开发中的应用和注意事项。
摘要由CSDN通过智能技术生成

3.1 纯函数如何处理副作用 useEffect 基本使用

纯函数的概念:

  1. 只负责自己的任务,它不会更改在该函数调用前就已存在的对象或变量

  2. 输入相同,则输出相同。给定相同的输入,纯函数应总是返回相同的结果

副作用的概念:

  1. 函数在执行过程中对外部造成的影响称之为副作用,例如:Ajax调用、DOM操作、与外部系统同步等

  2. 在React组件中,事件操作是可以处理副作用的,但有时候需要初始化处理副作用,那么就需要useEffect钩子

useEffect 触发时机: JSX 渲染后触发的

import { useRef, useEffect } from "react"
​
export default function App() { 
    const ref = useRef(null)
​
    // 副作用:不符合纯函数的规范
    // setTimeout(() => {
    //     ref.current.focus()
    // },3000)
​
    const handleClick = () => {
        // 副作用:符合纯函数的规范,因为事件是可以处理副作用的
        ref.current.focus()
    }
​
    // 可以在初始的时候进行副作用操作
    useEffect(() => {
        ref.current.focus() 
    })
​
    return (
        <div>
            hello App
            <button onClick={handleClick}>点击</button>
            <input type="text" ref={ref} />
        </div>
    )
}
port {  useEffect, useState } from "react"
​
export default function App() { 
    const [count,setCount]=useState(0)
​
    // 初始渲染和更新渲染,都会触发useEffect() -> 因为每次渲染JSX后,后会出发useEffect(),整个当前函数组件作用域的最后时机触发的
    useEffect(() => {
        console.log(count);
    })
​
    const handleClick = () => {
        setCount(count+1)
    }
​
    return (
        <div>
            hello App
            <button onClick={handleClick}>点击</button>{count}
        </div>
    )
}

3.2 分开处理副作用 useEffect 的依赖项的使用

可以通过将依赖项数组指定为调用的第二个参数来告诉 React 跳过不必要的重新运行 Effect

  1. 当依赖项为空数组的时候,只会初始触发,更新不会触发

  2. ESLint 会检测依赖项是否正确,包括:props, state, 计算变量等

import { useEffect, useState } from "react"
​
 export default function App() {
     const [count, setCount] = useState(0)
     const [msg, setMsg] = useState('hello React')
    
    // 初始的时候,所有的useEffect都会触发
    // 更新的时候,只有对应依赖项发生改变的才会触发
    // 内部是通过 Object.is() 来判定是否改变
     useEffect(() => {
         console.log(count);
     }, [count])
    
     useEffect(() => {
         console.log(msg);
     }, [msg])
    
     // 当为空数组的时候,只有初始化时会触发,更新的时候不会触发
     useEffect(() => {
         console.log(123);
     }, [])
    
     const handleClick = () => {
         setCount(count+1)
     }
     return (
         <div>
             hello App
             <button onClick={handleClick}>点击</button>
             {count},{msg}
         </div>
     )
 }
 
​
​

3.3 尽量在 useEffect 内定义函数

import { useEffect, useState } from "react"
​
​
export default function App() {
    const [count, setCount] = useState(0)
    
    useEffect(() => {
        const foo = () => {
            console.log(count);
         }
        foo()
    },[count])
    return (
        <div>
            hello App
        </div>
    )
}

3.4 useEffect 的清理操作的重要性

当卸载组件或更新组件的时候,可以通过useEffect来实现一些清理工作

ps:严格模式下,会检测useEffect是否实现了清理操作

初始化数据时,要注意清理操作,所以更简洁的方式是使用第三方,例如: ahooks 中的 useRequest

3.5 实验性的useEffectEvent

使用一个特殊的 Hook 调用 useEffectEvent 来从你的 Effect 中提取这个非反应性逻辑

实验版本: react@experimental、react-dom@experimental

3.6 useLayoutEffect 同步执行状态更新

  1. useEffect() 实在渲染被绘制到屏幕之后执行的,是异步的;useLayoutEffect() 是在渲染之后但在屏幕更新之前,是同步的

  2. 大部分情况下我们采用 useEffect(),性能更好。但当你的 useEffect 里面的操作需要处理 DOM,并且会改变样式,就需要用 useLayoutEffect ,否则可能会出现闪屏问题

    import { useEffect, useLayoutEffect, useRef } from "react"
    ​
    export default function App() {
        const ref = useRef(null)
        // useLayoutEffect 在 useEffect 之前触发
    ​
        useEffect(() => {
            console.log(1, ref.current);
        })
    ​
        useLayoutEffect(() => {
            console.log(2, ref.current);
        })
    ​
        return (
            <div>
                hello App
                <div ref={ref}>aaaaa</div>
            </div>
        )
    }

3.7 useInsertionEffect DOM更新前触发

useInsertionEffect 应用场景非常少,因为获取不到 DOM 元素,所以只能在 CSS-in-JS 库中才会使用

import { useInsertionEffect, useRef } from "react";
​
​
function App() {
    const ref = useRef(null)
​
    useInsertionEffect(() => {
        const style = document.createElement('style')
        style.innerHTML = `
            .box{
                background:red;
                width:100px;
                height:100px;
            }
        `
        document.head.appendChild(style)
    })
​
    return (
        <div>
            hello App
            <div className="box" ref={ref}>aaaaa</div>
        </div>
    )
}
​
export default App

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值