当前位置: 首页 > news >正文

react hooks的理解

面试必备!

useState:状态管理

useState有两个状态,一个是status,一个是setStatus

setStatus修改数据后,会触发<App/>的re-render

re-render:重新渲染,re-render并不意味着dom会更新,re-render是react自身执行一系列的组件自身生命周期,render,虚拟dom之间diff之后,如果dom发生变化,则更新新的dom,如果没有变化则不更新。

以下情况会导致re-render:

  1. 组件内部state变化:无论这个声明的state在组件的render中是否使用,state的变化都会导致组件自身及其子节点的re-render;
  2. 组件的props变化:这是站在子组件的角度上得出的结论,而子组件props变化来源于父组件的state,究其根本,还是组件内部state发生了变化;
  3. 用户交互事件触发或者接口请求数据响应;
  4. 组件订阅的context发生变化:组件订阅的context发生变化,是由于provider中的state发生了变化,同理,还是因为state发生变化导致的re-render
  5. 父组件的render:父组件render,子组件就会re-render.除非子组件是一个纯组件(纯组件:即他的props没有发生变化,那么他就不会更新,可以使用React.memo(),React.PureComponent将组件变为纯组件。)

题外话:如何避免不必要的re-render?

  1. 使用类组件PureComponent:引入PureComponent,在需要用到Component的地方修改为PureComponent
    import {PureComponent} from 'react';
    export class Root extends PureComponent{
    ...
    }//或者直接继承
    //export class Root extends React.PureComponent{...}
  2. 使用函数组件Memo:父组件中修改state时,下面这个子组件如果没有用到这个state,则不会re-render
    
    import { memo } from "react"
    const Memodemo=({props,children})=>{console.log('Memodemo')return <><p>这里用的是memo</p></>}export default memo(Memodemo)
  3. 利用高阶组件shouldComponentUpdate:组件在重新渲染之前(也就是虚拟dom对比完毕并生成最终dom之后),会调用该函数,该函数将是否重新渲染的权限交给开发者,若该函数返回true,则更新dom
    //下面这个示例,仅在value变化时发生dom更新,否则跳过dom更新
    class MyComponent extends React.Copmonent{shouldComponentUpdate(nextProps,nextState){return nextProps.value!===this.props.value}
    }
    //nextProps:即将传入的新的props
    //nextState:即将传入的新的state

useEffect:

useEffect接受两个参数,第一个参数是一个函数,必传,可以看作componentDidMount、componentDidUpdate、componentWillUnmount这三个函数的组合

useEffect中第一个参数如果添加了return返回一个函数,切换路由时,就会执行这个return返回的函数,相当于componentWillUnmount。

第二个参数可以不传或者传一个数组

那么useEffect会出现以下四种使用情况:

  1. 不传递第二个参数,当前组件每次渲染都会执行,包括state的每次更新都会触发useEffect
    useEffect(()=>{console.log('useEffect')}
    )
  2. 第二个参数传递空数组:只在挂载和卸载的时候执行
    useEffect(()=>{
    console.log('useEffect[]')
    },[])
  3. 第二个参数传递一个值
    useEffect(
    ()=>{
    console.log('当page发生修改的时候,会输出此行');
    },[page])
  4. 第二个参数传递多个值:数组中的任意一个或者多个发生变化,useEffect都会重新运行一次;
    useEffect(()=>{console.log('useEffect');
    },[level,level1])

componentDidMount :react在组件添加到屏幕上(挂在)后调用它,一般用于进入页面后,数据初始化

componentDidUpdate:页面中的state或者model中的state定义的变量发生了变化,这个方法就会执行;

componentWillUnmount:组件被移除屏幕(卸载)之前调用

这三个类生命周期和useEffect等同方式,看下面代码:

//类生命周期
class Example extends React.Component{constructor(props){super(props);this.state={count:0,dateNow:''}}componentDidMount(){    console.log('当前count=',this.state.count)this.timeFlag=setInterval(()=>{this.setState.dateNow=new Date()})}componentDidUpdate(){console.log('当前更新为count=',this.state.count)}componentWillUnmount(){clearInterval(this.timeFlag)}render(){return(<div><p>当前count={this.state.count}</P><p>当前时间={this.state.dateNow}</P><button onClick={()=>{this.state.count=this.state.count+1}}>count+1</button></div>)    }
}
//上面的类生命周期代码,等同于下面的代码
import {useState,useEffect} from 'react';
const Example=()=>{const [count,setCount]=useState(0);const [dateNow,setDateNow]=useState('');
//下面这一行没有写第二个参数,所以,当state中的变量发生变化时,这里的useEffect就会调用useEffect(()=>{console.log('当前count=',count)})
//这一行只有count发生变化,才会调用useEffectuseEffect(()=>{ console.log('当前更新为count=',count)},[count])uesEffect(()=>{const timeFlag=setInterval(()=>{setDateNow(new Date())        })return()=>{clearInterval(timeFlag)}},[])return(<div><p>当前count={count}</P><p>当前时间={dateNow}</P><button onClick={()=>{setCount(count+1)}}>count+1</button></div>)
}

useMemo:性能优化工具,主要解决使用react hooks产生的无用渲染的性能问题,类似于vue的computed,用于跳过昂贵的计算

useMemo使用方式为:useMemo(fn,arr);

第二个参数arr分以下几种情况:

  1. 不传,即useMemo(fn):每次更新都会重新计算
  2. arr=空数组[]:只会计算一次;
  3. arr=[a]:当a发生变化的时候,会重新执行fn;

useMemo的作用时跳过昂贵的计算,那我们看以下几个例子:

//当x或者y发生变化,组件re-render时,a都会进行重新计算,可以看到time的计算时间都是很长的
import { useMemo, useState } from "react"
const MemoPage=()=>{const [x,setX]=useState(1);const [y,setY]=useState(1);console.time('time')
let a=0;
for(var i=0;i<100000000;i++){a=a+i+y
}console.timeEnd('time')return(<><div>x={x}</div><div>y={y}</div><div>x={a}</div><div><button onClick={()=>setX(x+1)}>x++</button><button onClick={()=>setY(y+1)}>y++</button></div></>)
}
export default MemoPage

 

//用useMemo返回一个a,无论x还是y发生了修改, x={a}取的都是缓存中的a的值,不会进行重新计算,可以看到下图,time的计算时间变短
import { useMemo, useState } from "react"
const MemoPage=()=>{const [x,setX]=useState(1);const [y,setY]=useState(1);console.time('time')let a= useMemo(()=>{let a=0;for(var i=0;i<100000000;i++){a=a+i}return a},[])
//上面的[]必须写,如果不写,当x或者y发生修改,则a还是会重新计算console.timeEnd('time')return(<><div>x={x}</div><div>y={y}</div><div>x={a}</div><div><button onClick={()=>setX(x+1)}>x++</button><button onClick={()=>setY(y+1)}>y++</button></div></>)
}
export default MemoPage

 

 

//上面的代码a是固定不变的,假如,a是变化的呢?
//下面代码,当x发生变化时,a仍然取缓存,当y发生变化时,则重新计算
import { useMemo, useState } from "react"
const MemoPage=()=>{const [x,setX]=useState(1);const [y,setY]=useState(1);console.time('time')let a= useMemo(()=>{let a=0;for(var i=0;i<100000000;i++){a=a+i+y}return a},[y])console.timeEnd('time')return(<><div>x={x}</div><div>y={y}</div><div>x={a}</div><div><button onClick={()=>setX(x+1)}>x++</button><button onClick={()=>setY(y+1)}>y++</button></div></>)
}
export default MemoPage

 

上面是useMemo的主要作用

还有一些扩展作用 ,这些只是能达到效果,不是useMemo的主要作用

import { memo, useMemo, useState ,useRef} from "react";
const Child=memo(({a})=>{console.log('子组件')return <><div>子组件</div></>
})
const MemoPage=()=>{const [x,setX]=useState(1);const [y,setY]=useState(1);// let a=['a','b','c'];//直接写这一行,当x或者y发生变化时,子组件还是会重新渲染let a=useMemo(()=>['a','b','c'],[])//这一行子组件不会重新渲染
//    const [a,setA]=useState(['a','b','c'])//这一行子组件也不会重新渲染
// let a=useRef(['a','b','c']);//下面的子组件修改为<Child a={a.current}/>,也能达到一样效果console.log('父组件')return(<><div>x={x}</div><div>y={y}</div>{/* <div>x={a}</div> */}<div><button onClick={()=>setX(x+1)}>x++</button><button onClick={()=>setY(y+1)}>y++</button></div><Child a={a}/></>)
}
export default MemoPage

还没有写完,慢慢写~~

有需要补充的,麻烦私信我

useCallback:

useRefs:

useContext:


http://www.mrgr.cn/news/79307.html

相关文章:

  • 点云标注软件SUSTechPOINTS的安装和使用,自测win10和ubuntu20.04下都可以用
  • 小白爬虫——selenium入门超详细教程
  • 人大金仓(KingBaseEs)数据库操作手册
  • Docker-Compose环境变量
  • web基础和http协议
  • 「Mac畅玩鸿蒙与硬件43」UI互动应用篇20 - 闪烁按钮效果
  • Mysql数据库基础篇笔记
  • LearnOpenGL学习(高级OpenGL -- 深度测试,模板测试,)
  • xss学习前的基础
  • 期末复习-Hadoop名词解释+简答题+代码题hive
  • WordPress阅读文章显示太慢的处理
  • vue 一行显示的动态消息
  • 鸿蒙应用获取wifi连接的ip地址(官方文档获取的格式转换成192.168.1.xxx格式)
  • Linux-实用操作
  • Redis的五种数据类型(String、Hash、List)
  • centos 常见问题处理
  • Qt 面试题学习13_2024-12-1
  • ScribblePrompt 医学图像分割工具,三种标注方式助力图像处理
  • 构建万能 MOCK-API
  • Ubuntu显卡驱动安装