React hooks的优缺点详解

2022-04-15 0 941
目录
  • 前言
  • 优点:
  • 缺点:
    • 一、响应式的useEffect
    • 二、状态不同步
  • 怎么避免react hooks的常见问题

    前言

    Hook 是 React 16.8 的新增特性。它是完全可选的,并且100%向后兼容。它可以让你使用函数组件的方式,运用类组件以及 react 其他的一些特性,比如管理状态、生命周期钩子等。从概念上讲,React 组件一直更像是函数。而 Hook 则拥抱了函数,同时也没有牺牲 React 的精神原则。

    优点:

    1、代码可读性更强,原本同一块功能的代码逻辑被拆分在了不同的生命周期函数中,容易使开发者不利于维护和迭代,通过 React Hooks 可以将功能代码聚合,方便阅读维护。例如,每个生命周期中常常会包含一些不相关的逻辑。一般我们都会在 componentDidMount 和 componentDidUpdate 中获取数据。但是,同一个 componentDidMount 中可能也包含很多其它的逻辑,如设置事件监听,而之后需在 componentWillUnmount 中清除。相互关联且需要对照修改的代码被进行了拆分,而完全不相关的代码却在同一个方法中组合在一起。如此很容易产生 bug,并且导致逻辑不一致。
    2、组件树层级变浅。在原本的代码中,我们经常使用 HOC/render props 等方式来复用组件的状态,增强功能等,无疑增加了组件树层数及渲染,在 React DevTools 中观察过 React 应用,你会发现由 providers,consumers,高阶组件,render props 等其他抽象层组成的组件会形成“嵌套地狱”。而在 React Hooks 中,这些功能都可以通过强大的自定义的 Hooks 来实现。
    3、不用再去考虑 this 的指向问题。在类组件中,你必须去理解 JavaScript 中 this 的工作方式。

    缺点:

    一、响应式的useEffect

    写函数组件时,你不得不改变一些写法习惯。你必须清楚代码中useEffect和useCallback的“依赖项数组”的改变时机。有时候,你的useEffect依赖某个函数的不可变性,这个函数的不可变性又依赖于另一个函数的不可变性,这样便形成了一条依赖链。一旦这条依赖链的某个节点意外地被改变了,你的useEffect就被意外地触发了,如果你的useEffect是幂等的操作,可能带来的是性能层次的问题,如果是非幂等,那就糟糕了。

    所以,对比componentDidmount和componentDidUpdate,useEffect带来的心智负担更大。

    二、状态不同步

    函数的运行是独立的,每个函数都有一份独立的作用域。函数的变量是保存在运行时的作用域里面,当我们有异步操作的时候,经常会碰到异步回调的变量引用是之前的,也就是旧的(这里也可以理解成闭包)。比如下面的一个例子:

    import React, { useState } from "react";
    ​
    const Counter = () => {
      const [counter, setCounter] = useState(0);
    ​
      const onAlertButtonClick = () => {
        setTimeout(() => {
          alert("Value: " + counter);
        }, 3000);
      };
    ​
      return (
        <div>
          <p>You clicked {counter} times.</p>
          <button onClick={() => setCounter(counter + 1)}>Click me</button>
          <button onClick={onAlertButtonClick}>
            Show me the value in 3 seconds
          </button>
        </div>
      );
    };
    ​
    export default Counter;

    当你点击Show me the value in 3 seconds的后,紧接着点击Click me使得counter的值从0变成1。三秒后,定时器触发,但alert出来的是0(旧值),但我们希望的结果是当前的状态1。

    这个问题在class component不会出现,因为class component的属性和方法都存放在一个instance上,调用方式是:this.state.xxx和this.method()。因为每次都是从一个不变的instance上进行取值,所以不存在引用是旧的问题。

    其实解决这个hooks的问题也可以参照类的instance。用useRef返回的immutable RefObject(current属性是可变的)来保存state,然后取值方式从counter变成了: counterRef.current。如下:

    import React, { useState, useRef, useEffect } from "react";
    ​
    const Counter = () => {
      const [counter, setCounter] = useState(0);
      const counterRef = useRef(counter);
    ​
      const onAlertButtonClick = () => {
        setTimeout(() => {
          alert("Value: " + counterRef.current);
        }, 3000);
      };
    ​
      useEffect(() => {
        counterRef.current = counter;
      });
    ​
      return (
        <div>
          <p>You clicked {counter} times.</p>
          <button onClick={() => setCounter(counter + 1)}>Click me</button>
          <button onClick={onAlertButtonClick}>
            Show me the value in 3 seconds
          </button>
        </div>
      );
    };
    ​
    export default Counter;

    结果我们所期待,alert的是当前的值1。

    怎么避免react hooks的常见问题

    • 不要在useEffect里面写太多的依赖项,划分这些依赖项成多个单一功能的useEffect。其实这点是遵循了软件设计的“单一职责模式”。
    • 如果你碰到状态不同步的问题,可以考虑下手动传递参数到函数。如:
       // showCount的count来自父级作用域 
       const [count,setCount] = useState(xxx); 
       function showCount(){ console.log(count) } 
    
       // showCount的count来自参数 
       const [count,setCount] = useState(xxx); 
       function showCount(c){ console.log(c) }

    但这个也只能解决一部分问题,很多时候你不得不使用上述的useRef方案。

    3. 重视eslint-plugin-react-hooks插件的警告。

    4. 复杂业务的时候,使用Component代替hooks。

    以上就是React hooks的优缺点详解的详细内容,更多关于React hooks的优缺点的资料请关注NICE源码其它相关文章!

    免责声明:
    1、本网站所有发布的源码、软件和资料均为收集各大资源网站整理而来;仅限用于学习和研究目的,您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。 不得使用于非法商业用途,不得违反国家法律。否则后果自负!

    2、本站信息来自网络,版权争议与本站无关。一切关于该资源商业行为与www.niceym.com无关。
    如果您喜欢该程序,请支持正版源码、软件,购买注册,得到更好的正版服务。
    如有侵犯你版权的,请邮件与我们联系处理(邮箱:skknet@qq.com),本站将立即改正。

    NICE源码网 JavaScript React hooks的优缺点详解 https://www.niceym.com/33964.html