Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React Hooks优化 #27

Open
Vibing opened this issue Aug 7, 2020 · 0 comments
Open

React Hooks优化 #27

Vibing opened this issue Aug 7, 2020 · 0 comments

Comments

@Vibing
Copy link
Owner

Vibing commented Aug 7, 2020

React Hooks

react hooks 的使用需要在 function component 组件中,本文讲述在使用 react hooks 中你需要注意的一些事情

状态每次改变,整个 function 都会重新执行

可能导致:函数的每次执行,其内部定义的变量和方法都会重新创建,也就是说会从新给它们分配内存,这会导致性能受到影响

看下面这个例子:

import React, { useState, ReactElement } from 'react'
import { Button } from 'antd'

let num = 0; // 用于记录当前组件执行次数

export default (): ReactElement => {
  console.log('render num: ', ++num) // 打印执行次数

  let [count, setCount] = useState(0)

  const handleClick = () => {
    setCount(++count)
  }

  return (
    <>
      <p>count: {count}</p>
      <Button type="primary" onClick={handleClick}>
        Button
      </Button>
    </>
  )
}

初始化时执行了一次:

现在我点三次按钮,让 count 状态改变:

可见,每改变一次 count, 该组件对应的整个 function 会重新执行,其内部变量和方法会重新创建,从而影响性能。

解决方法:

  • 变量尽量放在函数外部
  • 方法使用 useCallback 包裹起来

使用方法:

const handleClick = useCallback(()=>{
    // 业务代码
},[ count ])

useCallback 的作用:组件初始化时,将第一个参数函数“缓存”起来,只有在第二个参数(数组中的值)有变化时,被包裹的函数才会重新被创建,否则不会重新创建。

总结:变量尽量放在组件外部定义,函数使用 useCallback 包裹起来,避免组件 render 时重复创建。

父组件更新,子组件也跟着执行

再看个例子,我们把上面例子作为父组件,在里面添加一个子组件.

父组件:

export default (): ReactElement => {
  let [count, setCount] = useState(0)

  const handleClick = useCallback(() => {
    setCount(++count)
  }, [count])

  return (
    <>
      <p>count: {count}</p>
      
      {/* 这里添加一个子组件 */}
      <ChildrenComponent />

      <Button type="primary" onClick={handleClick}>
        Button
      </Button>
    </>
  )
}

子组件代码:

export default (): ReactElement => {
  console.log('children render')

  return <div>children component</div>
}

现在我再点三次按钮,让父组件 render 三次:

大爷的,子组件打印三次,表示执行了三次。

这肯定不是我想要的,我想要的是子组件需要被渲染的时候再去执行,那么如何解决?

答:使用 React.memo

React.memo 类似 class 组件里的 PureComponent , 能帮助我们控制合适重新渲染组件。

注意:说它类似,但不完全一样,它更像是 PureComponent + shouldComponentUpdate 的结合。
PureComponent 通过 props 和 state 的浅比较来判断要不要重新渲染组件。

那么在 react hooks 里如何去写呢

我们把子组件加上 React.memo :

export default React.memo(
  (): ReactElement => {
    console.log('children render')

    return <div>children component</div>
  },
)

现在再点三次按钮:

可见,子组件不再打印,也就是不再执行了。

React.memo 也提供了 shouldComponentUpdate 功能,用于自定义比较来决定是否渲染:

React.memo(MyComponent, (prevProps, nextProps)=>{
 // 如果传递 nextProps 渲染会返回与传递 prevProps 渲染相同的结果,则返回 true,否则返回 false.
 
 // return true:不渲染  return false:渲染
})

总结

  • 使用 useCallback 缓存定义的函数
  • 使用 React.memo 避免不必要的 render

如果有更好的建议,请留言,多谢

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant