简单有效的编写或优化Hooks组件

389 阅读3分钟

相信现在有很多写React的小伙伴喜欢hooks的简洁,从class迁移到了Hook的组件方式!

先简单回顾下hook组件的一般写法

1、 useState

用来获取和修改 组件中用到的状态

const [state, setState] = useState(initialState);

2、useEffect

用来处理组件副作用

useEffect(()=>{
...
},[...]);

赋值给 useEffect 的函数会在组件渲染到屏幕之后执行

3、 useContext

用来接收一个 context 对象(React.createContext 的返回值)并返回该 context 的当前值。当前的 context 值由上层组件中距离当前组件最近的 <MyContext.Provider> 的 value prop 决定。

const Context = React.createContext(null);
...
<Context.Provider value={appstate}>
</Context.Provider>
...
const _context = useContext(Context);

4、 useCallback

useCallback用来缓存一个函数

useCallback(fn, deps)

5、 useMemo

useMemo用来缓存一个值

useMemo(()=> (...), deps)

以上是HOOK提供的api。 用HOOK编写REACT组件是一件容易的事情。但是编写好组件确不很容易。需要正确理解React推出这些api背后真正的含义。

1、useState 的运用

函数组件没有生命周期。在我组件中我想要获取一个最新值 一个最新的远程数据该怎么做呢? useState 的 setState 方法会触发组件的重渲染。这就间接的提供了在组件的任何位置获取最新变量值的可能。

import {useState} from 'react';

export default function App() {

const [state, setState] = useState(0);

const handleclick = ()=>setState(item=>++item)

return (

    <div className="App">

        <h1>Hello ,{state}</h1>

        <button onClick={handleclick}>click!</button>

    </div>

);

}

上面的handleclick的每次执行都会调用setState,随后react就会重渲染整个组件!!! 包括里面的所有函数方法!随着组件的重新执行,自然组件内申明的所有变量最新值都会在本次运行中获得。

也就是说useState不仅仅有获取最新state的能力,他可以重渲染整个组件!

而在实际项目中可能会在一个组件中用到很多的变量和数据。自然就会用到很多的useState, 每次setState都会重渲染组件和组件的子组件,这个时候自然大家会有一种焦虑 ,这么多重渲染会不会造成性能问题,页面卡顿呢?有没有什么优化方案呢? 很多人想到了useCallback 和 useMemo。并且使用他们来缓存函数和变量。

const handleclick = useCallback(()=>setState(item=>++item),[])

问题表面上看似解决了! 如果仔细了解就会知道useCallback 和 useMemo 的第二个参数 是个依赖数组,每次运行通过浅比较,如果依赖变化 则重新执行被包裹的函数。在这个比较的过程中也是一个消耗。

性能优化不是免费的。它们总是伴随着成本,但并不总是伴随着抵消成本的收益。

useCallback \ useMemo

一般用来包装需要传递给子组件得 方法 和复杂对象  来避免不必要得 子组件重渲染

通常用在缓存 父组件 传递给子组件得 引用参数 上;这样可以弥补引用参数浅比较总是不相等,而引起得每次不必要得渲染!

除此之外,还有以下优化建议:

  1. 如果一个函数没有使用组件内的任何值,你应该把它提到组件外面去定义,这是最简单的反正不必要渲染的途径!
  2. useState这个钩子函数只在没有时候才创建,之后都是读取,不影响性能。
  3. effect中的依赖数组如果是个函数,可以通过useCallback(()=》{},[])方法.该方法只有在依赖改变时,才会改变引用.这样可以保持正确的依赖比较。
  4. 降低组件的复杂度,利用函数式思想,使组件细粒度化,减少不必要的渲染!