独立的渲染单元
React的State的更新会导致组件渲染,比如一个页面由多个模块组成,一个小模块的更新可能会导致全局的一个页面渲染。虽然React为我们做了优化,但是我们还是应该尽量减少这种小的模块更新而导致全局渲染的情况。
示例代码
function ComponentA(){ const [ dataA, setDataA ] = useState(null) useEffect(()=>{ getDataA().then(res=> setDataA(res.data) ) },[]) return <div> { /* 用 dataA 数据做展示渲染 */ } </div> } function ComponentB(){ const [ dataB, setDataB ] = useState(null) useEffect(()=>{ getDataB().then(res=> setDataB(res.data) ) },[]) return <div> { /* 用 dataB 数据做展示渲染 */ } </div> } function ComponentC(){ const [ dataC, setDataC ] = useState(null) useEffect(()=>{ getDataC().then(res=> setDataC(res.data) ) },[]) return <div> { /* 用 dataC 数据做展示渲染 */ } </div> } function Index (){ return <div> <ComponentA /> <ComponentB /> <ComponentC /> </div> }
如上面的代码,我们可以看到state的分布在不同组件中,他们自己维护自己内部的组件。不会因为更新了某一个数据而导致全局渲染
React.memo减少不必要的渲染
无状态组件的更新是从头到尾的更新,如果你想要从新渲染一部分视图,而不是整个组件,那么用useMemo是最佳方案,避免了不需要的更新,和不必要的上下文的执行。下面我们通过一段代码来分析
import React, { useEffect, useState, useRef,useMemo} from 'react'; export default function DemoMemo() { const [message,setMessage] = useState(1); const [notChange,setNotChange] = useState(100); const handleClick = ()=>{ const newMsg = message < 10000 ? message+1 : message; if(message>10 && message<15){ setNotChange(message); } return setMessage(newMsg); } const Memo =()=> useMemo(()=>{ console.log('我再memo中创建的'); return <h2>{`memo组件 依赖:${notChange} 不依赖的值:${message}`}</h2> },[notChange]) const NormalWidget =()=>{ console.log('我是普通函数组件创建的'); return <h2>普通组件{message}</h2> } return ( <div> <div>{message}</div> <button onClick={handleClick} >加数</button> {Memo()} <NormalWidget></NormalWidget> </div> ) }
useCallback
useMemo和useCallback接收的参数都是一样,都是在其依赖项发生变化后才执行,都是返回缓存的值,区别在于useMemo返回的是函数运行的结果,useCallback返回的是函数,这个回调函数是经过处理后的也就是说父组件传递一个函数给子组件的时候,由于是无状态组件每一次都会重新生成新的props函数,这样就使得每一次传递给子组件的函数都发生了变化,这时候就会触发子组件的更新,这些更新是没有必要的,此时我们就可以通过usecallback来处理此函数,然后作为props传递给子组件
使用useRef作数据缓存
在class
声明组件中,我们可以直接把数据绑定给this
上,来作为数据缓存。
在无状态组件中, 我们不能往问this
,但是我们可以用useRef
来解决问题。
import { Button } from 'antd' import React, { useState, useRef } from 'react' export default function RefDemo() { const [state, setstate] = useState(1) const ref = useRef(1); const addState = () => { setstate(pre => pre + 1); } const addRef = () => { ref.current = ref.current + 1; } console.log(`页面刷新了,state:${state} ref:${ref.current}`); return ( <div> <h1>不引用state的值,但是需要更新存储值,尽量用ref来存储,更新state会导致组件函数执行</h1> <Button onClick={addState}>更新state的缓存值</Button> <Button onClick={addRef}>更新ref的缓存值</Button> </div> ) }