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 (
<>
count: {count}
>
)
}
初始化时执行了一次:
现在我点三次按钮,让 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 (
<>
count: {count}
{/* 这里添加一个子组件 */}
>
)
}
子组件代码:
export default (): ReactElement => {
console.log('children render')
return children component
}
大爷的,子组件打印三次,表示执行了三次。
这肯定不是我想要的,我想要的是子组件需要被渲染的时候再去执行,那么如何解决?
答:使用 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 children component
},
)
现在再点三次按钮:
可见,子组件不再打印,也就是不再执行了。
React.memo 也提供了 shouldComponentUpdate 功能,用于自定义比较来决定是否渲染:
React.memo(MyComponent, (prevProps, nextProps)=>{
// 如果传递 nextProps 渲染会返回与传递 prevProps 渲染相同的结果,则返回 true,否则返回 false.
// return true:不渲染 return false:渲染
})
总结
- 使用 useCallback 缓存定义的函数
- 使用 React.memo 避免不必要的 render
如果有更好的建议,请留言,多谢