面试必备!
useState:状态管理
useState有两个状态,一个是status,一个是setStatus
setStatus修改数据后,会触发<App/>的re-render
re-render:重新渲染,re-render并不意味着dom会更新,re-render是react自身执行一系列的组件自身生命周期,render,虚拟dom之间diff之后,如果dom发生变化,则更新新的dom,如果没有变化则不更新。
以下情况会导致re-render:
- 组件内部state变化:无论这个声明的state在组件的render中是否使用,state的变化都会导致组件自身及其子节点的re-render;
- 组件的props变化:这是站在子组件的角度上得出的结论,而子组件props变化来源于父组件的state,究其根本,还是组件内部state发生了变化;
- 用户交互事件触发或者接口请求数据响应;
- 组件订阅的context发生变化:组件订阅的context发生变化,是由于provider中的state发生了变化,同理,还是因为state发生变化导致的re-render
- 父组件的render:父组件render,子组件就会re-render.除非子组件是一个纯组件(纯组件:即他的props没有发生变化,那么他就不会更新,可以使用React.memo(),React.PureComponent将组件变为纯组件。)
如何避免不必要的re-render?
- 使用类组件PureComponent:引入PureComponent,在需要用到Component的地方修改为PureComponent
import {PureComponent} from 'react'; export class Root extends PureComponent{ ... } //或者直接继承 //export class Root extends React.PureComponent{...}
- 使用函数组件Memo:父组件中修改state时,下面这个子组件如果没有用到这个state,则不会re-render
import { memo } from "react" const Memodemo=({props,children})=>{ console.log('Memodemo') return <> <p>这里用的是memo</p> </> } export default memo(Memodemo)
- 利用高阶组件shouldComponentUpdate
useEffect:
useEffect接受两个参数,第一个参数是一个函数,必传,可以看作componentDidMount、componentDidUpdate、componentWillUnmount这三个函数的组合
useEffect中第一个参数如果添加了return返回一个函数,切换路由时,就会执行这个return返回的函数,相当于componentWillUnmount。
第二个参数可以不传或者传一个数组
那么useEffect会出现以下四种使用情况:
- 不传递第二个参数,当前组件每次渲染都会执行,包括state的每次更新都会触发useEffect
useEffect( ()=>{console.log('useEffect')} )
- 第二个参数传递空数组:只在挂载和卸载的时候执行
useEffect(()=>{ console.log('useEffect[]') },[])
- 第二个参数传递一个值
useEffect( ()=>{ console.log('当page发生修改的时候,会输出此行'); },[page])
- 第二个参数传递多个值:数组中的任意一个或者多个发生变化,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发生变化,才会调用useEffect
useEffect(()=>{ 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:性能优化工具,类似于vue的computed
useMemo只有数据依赖项中的值共发生改变时才会重新计算。
还没有写完,慢慢写~~
有需要补充的,麻烦私信我