React性能优化

88 阅读1分钟
1、概述

React为什么要掌握性能优化。如下图,我们只修改了Content的内容啊,为什么Header组件和Comment组件依然执行了,能打印出内容。 image.png

我们写的代码
import React, { useState } from 'react'

export default function App() {
  const [num, setNum ]  = useState(0)
  return (
    <div>
      <input value={num} onChange={(e) => setNum(e.target.value)}></input>
      <p>num is {num}</p>
      <ExpensiveComp/>
    </div>
  )
}

function ExpensiveComp() {
  console.log('运行了无关组件')
  return <p>无关组件</p>
}

调试结果

image.png

结论

每次改变输入框的内容都会让我们的整个页面全部遍历

2、原因

因为我们将变的部分和不变的部分是糅合在一起的,什么是变化的部分呢?

主要是这3个属性props、state、context。根本就是state改变了,导致当前页面的重新渲染。如果把没有关系的状态分割开呢

代码优化
export default function App() {
  return (
    <div>
      <InputNum/>
      <ExpensiveComp />
    </div>
  )
}

function InputNum() {
//状态抽离
  const [num, setNum] = useState(0)
  return (
    <>
      <input value={num} onChange={(e) => setNum(e.target.value)}></input>
      <p>num is {num}</p>
    </>
  )
}

function ExpensiveComp() {
  console.log('运行了无关组件')
  return <p>无关组件</p>
}

调试结果

image.png

3、其他情况怎么将状态抽离开
1、状态在父组件中
export default function App() {
  const [num, setNum] = useState(0)
  return (
    <div title={num + ''}>
      <input value={num} onChange={(e) => setNum(e.target.value)}></input>
      <p>num is {num}</p>
      <ExpensiveComp />
    </div>
  )
}


function ExpensiveComp() {
  console.log('运行了无关组件')
  return <p>无关组件</p>
}

优化---ExpensiveComp组件的props是没有改变的不应该更新

export default function App() {

//没有状态了,
  return (
    <InputWrapper>
      <ExpensiveComp/>
    </InputWrapper>
  )
} 

function InputWrapper(props) {
  const [num, setNum] = useState(0)
  return (
    <div title={num + ''}>
      <input value={num} onChange={(e) => setNum(e.target.value)}></input>
      <p>num is {num}</p>
      {props.children}
    </div>
  )
}

2、使用cotext的时候怎么优化

问题代码

const numCtx = React.createContext(0)
const updateNumCtx =React.createContext(()=>{})
export default function App() {
  const [num, setNum] = useState(0)
  return (
    <numCtx.Provider value={num}>
      <updateNumCtx.Provider value={setNum}>
        <ExpensiveComp/>  
      </updateNumCtx.Provider>
    </numCtx.Provider>
  )
}


function ExpensiveComp() {
  return (
    <>
    <Button/>
    <Show/>
    </>
  )
}

function Button() {
  const updateNum = useContext(updateNumCtx)
  console.log('btn')
  return (
    <button onClick={() => updateNum(Math.random())}>产生随机数</button>
  )
}

function Show(){
  const num = useContext(numCtx)
  console.log('show')
  return (
    <p>num is {num}</p>
  )
}

image.png

image.png

优化代码 --- 可以考虑优化api,


只有使用优化api包裹一下就能够命中React的优化策略
function ExpensiveComp() {
  return useMemo(()=>{
    return  <>
    <Button />
    <Show />
  </>
  },[])
}