REACT性能优化

101 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路

REACT性能优化

react常见性能优化方法

1、组件按需加载 组件按需加载又可以分为懒加载、懒渲染、虚拟列表三类

懒加载

react懒加载主要是Suspense实现

参考文档:www.jb51.net/article/262…

import React, {Suspense, Lazy} from "react";
 let flag = true

 // 使用lazy做动态导入,并做错误处理
const ChildApp = Lazy(() => {
    return new Promise((resolve,reject) => {
        if(flag){
            resolve(import "./ChildrenApp")
        }else{
            reject("somthing wrong")
        }
    })
})


const APP = () => {

    return (
        <div>
          <Suspense  fallback="loading...">
            <Children />
          </suspense>
      
        </div>
    )
}



懒渲染

react中使用react-visibility-obserreact-visibility-observe进行监听

import VisibilityObserver,{useVisibilityObserver} from "react-visibility-observer";

const VisibilityChildren = (callback, children) => {
    const { isVisible } = useVisibilityObserver()
    useEffect(() => {
        if(isvisibility){
            callback(isvisibility)
        }
    },[callback,isvisible])

    return <Children />
}


const lazyRender = () => {
  const [isRendered,setIsRendered] = useState(false)

  if(!isRendered){
    return (
        <VisibilityObserver>
           <VisibilityChildren
            callback={(isvisible) => {
                if(isvisible) {
                    setIsRendered(true)
                }
            }}
            >
             <span />
           </VisibilityChildren>
        </VisibilityObserver>
        )
  }

return (
    <div>到可视区域才渲染</div>
)

}

2、跳过不必要的组件更新

React.PureComponent和React.memo实现控制子组件更新次数 在react中当父组件的发生状态更新进行render时,即使父组件传给子组件的state和props都没有变化,组件同样也会rerender, React.pureComponent和React.memo的作用就是阻止这种不必要的子组件的渲染

//React.PureComponent主要搭配类组件 //React.memo搭配函数组件

const App = () => {
    const [list,setList] = useState([{
        title:"React",
        level:"six",  
        }, 
       {
         title:"vue",
         level:"five",
       }])

       useEffect(() => {
        setTimeout(() => {
            settList([{
                title:"React",
                level:"six",  
                }, 
                {
                 title:"vue",
                 level:"five",
                }])
        },1000)
       },[])
    return (
        <div>
        {
            list.map(item => {
                // memo进行的是浅比较,当传值为数组或者对象时,仍然会render字组件
                <Children data={item}  />

                //传值改为浅层值
                <Children {...item}>
              
            })
        }
        
        </div>
    )
}

// Children 会重复render
const Children = (props) => {
    return (
        <div>{props.data.title} : {props.data.level}</div>
    )
}

// 使用memo
const Children = React.memo((props) => {
     return (
        <div>{props.data.title} : {props.data.level}</div>
    )
})

3、使用useCallback和useMemo稳定状态

useCallback的重要作用是当父组件的函数作为子组件的回调时,每当父组件更新,会重新创建该函数,所以子组件检测到函数变化会rerender,而实际情况,当函数没有变化时,且依赖没有变化,子组件是不需要rerender的,所以useCallback的作用就是,当依赖没有变化时,给子组件传递一个同样的值,使子组件不更新



const Child = ({
    reRenderEvent,
    noReRenderEvent
}) => {

    console.log("子组件加载")

    return <div>
        // 点击时子组件会rerender
        <a onClick={reRenderEvent}>我是子组件点击事件,会导致子组件渲染</a>
        <br />
        // 子组件不会rerender
        <a onClick={noReRenderEvent}>我是子组件点击事件,不会导致子组件渲染</a>

    </div>
}


export const Parent = () => {
    const [count,setCount] = useState(0)
    const reRenderEvent = () => {
        console.log('count',count)
        setCount(count + 1)
    }

    const noReRenderEvent = useCallback(() => {
        console.log('count',count)
        setCount(count + 1)

    },[])
    return (
        <div>
            <p>I am parent component</p>
            <Child  
              reRenderEvent = {reRenderEvent}
              noReRenderEvent = {noReRenderEvent}
             />
        </div>
    )
}

useMemo的使用场景是,当组件更新时,某些计算量比较大的值很有可能被重新计算,useMemo用来缓存计算值,避免重复计算,

useMemo还可以直接返回dom,当返回dom时,在依赖不变的情况下将跳过render阶段

export const Memo = () => {
    const [count,setCount] = useState(0)
    const [sum,setSum] = useState(0)

    // count 和sum改变都会触发计算
    const countCaculate = (() => {
        console.log("caculation of the count")
    })()
    // 只有依赖sum改变才会触发计算
    const sumCaculate = useMemo(() => {
        console.log("caculation of the sum")
    },[sum])

    // 直接返回dom
    const memoDom = useMemo(() => {
     return <p>直接返回dom</p>
    },[])
    return (
        <div>
            <button onClick={() => {
                setCount(count + 1)
            }}>click me count add one</button>
            <br />
            <button onClick={() => {
                setSum(sum + 1)
            }}>click me sum add one</button>
        </div>
    )
}