React在16.8版本中发布了新的 React Hook特性,新特性的目的是降低组件代码量, 将逻辑相关代码放到一个函数内,将逻辑不相关代码放到不同函数内,并不在区分是否是第一次render。下面是传统class代码实现的显示点击次数并更新document title为点击次数
这里的一个问题就是利用 componentDidMount 和 componentDidUpdate显著区分了是否是第一次render,在这个情况下我们并不需要区分,那这里就出现了代码冗余,使用useEffect可以极大缩减代码量。
第二种比较常见的是我们需要在组件render之后订阅或者开启timer, 并在组件卸载的时候清除订阅和timer。 传统class实现的好友在线状态订阅代码如下
这里订阅和取消订阅逻辑之间存在很强的关联,却被放在不同的函数里面, useEffect hook允许以返回函数的形式来清除 side effects
下面逐一回顾新增hook函数。
useState
const [state, setState] = useState(initialState);
复制代码
接收一个initialState参数初始化state值,setState函数和class中的setstate函数一样,唯一区别是hook返回的setstate并不做新state的默认拼接,所以state是object的话建议使用如下代码更新
setState(prevState => { // Object.assign would also work return {...prevState, ...updatedValues}; });
useEffect
这里有一个需要注意的点在于组件每一次 re-render之前都会调用useeffect的返回函数清除所有sideeffect, 然后在re-render之后再次执行sideeffect, 这里存在性能隐患,有时候并不需要每一次都需要这个清除再调用过程。UseEffect 提供了第二个参数,是一个数组。 组件仅在数组内任一参数发生变化时执行上面提到的清除Effect,再调用过程。极端情况是提供空数组作为第二个参数, 那么useEffect仅在挂载时调用,卸载时清除。
useContext
接收组件树中传递下来的最新的context值得变化并触发re-render
useCallback和 useMemo
因为hooks应用于函数组件,每一次re-render都会再次调用这个函数组件函数体? (待确认) 或 return部分? (待确认,所以父组件更新时,如果子组件使用了父组件定义的回调函数,或值, 子组件也会触发re-render。 这就会触发一些不必要的re-render, 以前我们可以在componentshouldupdate这个生命周期函数中避免这个问题, 现在我们可以使用 useCallback 和 useMemo来声明 传入子组件的函数,仅当回调函数或传入值得依赖参数发生变化时,子组件触发re-render。
useRef
相比于之前的ref属性,useRef更加强大,不仅提供了操作原生dom的能力,还可以保存不会影响render的可变状态值,他的用法基本和state一样,但是不会触发re-render。
参考文章: reactjs.org/docs/hooks-…