好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

React Hooks常用场景的使用(小结)

前言

React 在 v16.8 的版本中推出了 React Hooks 新特性。在我看来,使用 React Hooks 相比于从前的类组件有以下几点好处:

代码可读性更强,原本同一块功能的代码逻辑被拆分在了不同的生命周期函数中,容易使开发者不利于维护和迭代,通过 React Hooks 可以将功能代码聚合,方便阅读维护; 组件树层级变浅,在原本的代码中,我们经常使用 HOC/render props 等方式来复用组件的状态,增强功能等,无疑增加了组件树层数及渲染,而在 React Hooks 中,这些功能都可以通过强大的自定义的 Hooks 来实现;

关于这方面的文章,我们根据使用场景分别进行举例说明,帮助你认识理解并可以熟练运用 React Hooks 大部分特性。

博客 github地址为:https://github.com/fengshi123/blog

一、State Hook

1、基础用法

?

function State(){

   const [count, setCount] = useState(0);

   return (

       <div>

           <p>You clicked {count} times</p>

           <button onClick={() => setCount(count + 1)}>

               Click me

           </button>

       </div>

   )

}

2、更新

更新分为以下两种方式,即直接更新和函数式更新,其应用场景的区分点在于:

直接更新不依赖于旧 state 的值; 函数式更新依赖于旧 state 的值;

?

// 直接更新

setState(newCount);

 

// 函数式更新

setState(prevCount => prevCount - 1);

3、实现合并

与 class 组件中的 setState 方法不同,useState 不会自动合并更新对象,而是直接替换它。我们可以用函数式的 setState 结合展开运算符来达到合并更新对象的效果。

?

setState(prevState => {

   // 也可以使用 Object.assign

   return {...prevState, ...updatedValues};

});

4、惰性初始化 state

initialState 参数只会在组件的初始渲染中起作用,后续渲染时会被忽略。其应用场景在于:创建初始 state 很昂贵时,例如需要通过复杂计算获得;那么则可以传入一个函数,在函数中计算并返回初始的 state,此函数只在初始渲染时被调用:

?

const [state, setState] = useState(() => {

   const initialState = someExpensiveComputation(props);

   return initialState;

});

5、一些重点

(1)不像 class 中的 this.setState ,Hook 更新 state 变量总是替换它而不是合并它;
(2)推荐使用多个 state 变量,而不是单个 state 变量,因为 state 的替换逻辑而不是合并逻辑,并且利于后续的相关 state 逻辑抽离;
(3)调用 State Hook 的更新函数并传入当前的 state 时,React 将跳过子组件的渲染及 effect 的执行。(React 使用 Object.is 比较算法 来比较 state。)

二、Effect Hook

1、基础用法

?

function Effect(){

   const [count, setCount] = useState(0);

   useEffect(() => {

     console.log(`You clicked ${count} times`);

   });

 

   return (

       <div>

           <p>You clicked {count} times</p>

           <button onClick={() => setCount(count + 1)}>

               Click me

           </button>

       </div>

   )

}

2、清除操作

为防止内存泄漏,清除函数会在组件卸载前执行;如果组件多次渲染(通常如此),则在执行下一个 effect 之前,上一个 effect 就已被清除,即先执行上一个 effect 中 return 的函数,然后再执行本 effect 中非 return 的函数。

?

useEffect(() => {

   const subscription = props.source.subscribe();

   return () => {

     // 清除订阅

     subscription.unsubscribe();

   };

});

3、执行时期

与 componentDidMount 或 componentDidUpdate 不同,使用 useEffect 调度的 effect 不会阻塞浏览器更新屏幕,这让你的应用看起来响应更快;(componentDidMount 或 componentDidUpdate 会阻塞浏览器更新屏幕)

4、性能优化

默认情况下,React 会每次等待浏览器完成画面渲染之后延迟调用 effect;但是如果某些特定值在两次重渲染之间没有发生变化,你可以通知 React 跳过对 effect 的调用,只要传递数组作为 useEffect 的第二个可选参数即可:如下所示,如果 count 值两次渲染之间没有发生变化,那么第二次渲染后就会跳过 effect 的调用;

?

useEffect(() => {

   document.title = `You clicked ${count} times`;

}, [count]); // 仅在 count 更改时更新

5、模拟 componentDidMount

如果想只运行一次的 effect(仅在组件挂载和卸载时执行),可以传递一个空数组([ ])作为第二个参数,如下所示,原理跟第 4 点性能优化讲述的一样;

?

useEffect(() => {

   .....

}, []);

6、最佳实践

要记住 effect 外部的函数使用了哪些 props 和 state 很难,这也是为什么 通常你会想要在 effect 内部 去声明它所需要的函数。

?

// bad,不推荐

function Example({ someProp }) {

   function doSomething() {

     console.log(someProp);

   }

 

   useEffect(() => {

     doSomething();

   }, []); //

dy("nrwz");

查看更多关于React Hooks常用场景的使用(小结)的详细内容...

  阅读:37次