如何优雅地使用React Hooks

news/2024/7/15 17:57:31 标签: react.js, javascript, 前端

一、理解什么是Hooks

在React中,Hooks其实就是一个函数,这个函数的命名以use开头、函数return一个结果;React Hooks其实就是封装了一些通用的、公共的方法,就是一些通用的工具。

二、React Hooks分为官方Hooks和自定义Hooks

官方Hooks是指React官方推荐的一些Hooks,如:useState、useEffect、useContext、useRef、useMemo、useCallback、useReducer、......;

1.useState:让React函数组件也可以使用状态,使用方法:const [ age, setAge ] = useState(35).

2.useEffect:在React函数组件里,没有组件生命周期这一说法,所以可以使用useEffect来替代组件生命周期,使用方法如下:

javascript">useEffect( () => {
    window.addEventListener('message', handleMessage );

    return () => {
        window.removeEventListener('message', handleMessage );
    }
}, [] )

useEffect接收的一个回调函数相当于是componentDidMount和componentDidUpdate,回调函数return的这一个回调相当于是componentWillUnmount;useEffect接收的第二个数组是依赖项,如果只是模拟组件生命周期,可以传空数组,通常这个依赖项不要传入过多或过于复杂,因为当依赖项发生变化useEffect中的回调函数会重新执行。

3.useContext:用于父组件向子组件的跨级传参,使用比较简单,直接参考官方文档即可。

4.useRef:绑定元素ref,通常用于调用子组件身上的方法;this.formRef.current.doReq()...。

5.useMemo:用于缓存函数的计算结果,与Vue中的计算属性类似;使用方法如下:

javascript">const result = useMemo( () => {
    const res = a + b;
    return res;
}, [a,b] )

useMemo的第二个参数为依赖项数组,依赖项发生变化则重新计算结果。

6.useCallback:缓存函数(缓存函数地址),通常与React.memo()一起使用;React.memo()是通过校验props中的数据是否改变的来决定组件是否需要重新渲染的一种缓存技术,具体点说React.memo()其实是通过校验Props中的数据的内存地址是否改变来决定组件是否重新渲染组件的一种技术。useCallback通常用于缓存父组件向子组件传递的函数,当父组件发生变化时会重新渲染,此时若变化与子组件无关,子组件不应重复渲染;useCallBack并不能阻止函数重新创建,它只能通过依赖决定返回新的函数还是旧的函数,从而在依赖不变的情况下保证函数地址不变。其使用方法如下:

javascript">import {useCallBack,memo} from 'react';

const Parent = ( props ) => {
    const [parentData, setParentData] = useState(66);  
    
    const toChildFun = useCallBack( () => {
        console.log("需要传入子组件的函数");
        
    }, [])
    
    return (<div>
          <Button onClick={() => setParentState(val => val+1)}>
              点击改变父组件中与Child组件无关的state
          </Button>
          
          <Child fun={toChildFun}></Child>
    <div>)
}

const Child = memo(( props ) => {
    console.log('子组件渲染了');
    return <div>子组件<div>
} )

7.useReducer:相当于写redux,直接根据官方文档进行使用。

官方文档里还有一些其他的Hooks,其实使用起来都比较方便,直接看文档使用就行了,在这里就列举以上几种常用的官方Hooks。

自定义Hooks其实就是根据自己的开发需求,封装一些通用的、公共的工具函数,使用起来其实就和官方推荐的Hooks是一样的。

自定义 Hooks 允许共享有状态逻辑,而不是状态本身,例如:

javascript">import { useState } from 'react';
// 自定义Hooks 
function useCounter(initialValue) {
  const [count, setCount] = useState(initialValue);
  function increment() {
    setCount(count + 1);
  }
  return [count, increment];
}

// 在其他组件进行使用
import useCounter from './useCounter';
function Counter() {
	const [count1, increment1] = useCounter(0);
	const [count2, increment2] = useCounter(100);
  return (
    <div>
      <p>Count1: {count1}</p>
      <button onClick={increment1}>Increment1</button>
       <p>Count2: {count2}</p>
      <button onClick={increment2}>Increment2</button>
    </div>
  );
}

当我们点击 Increment2 时,并不会影响 count1 ,因为每一个 useCounter 的调用都是独立的,其内部状态也是独立的。

三、React Hooks使用方法

1.只能在函数外层调用 Hook,不要在循环、条件判断或者子函数中调用。

2.只能在 React 的函数组件(顶部)和自定义 Hook 中调用 Hook。不要在其他 JavaScript 函数中调用。

3.在组件中 React 是通过判断 Hook 调用的顺序来判断某个 state 对应的 useState的,所以必须保证 Hook 的调用顺序在多次渲染之间保持一致,React 才能正确地将内部 state 和对应的 Hook 进行关联。

四、用Hooks替代一些高阶组件会更有优势

假如现在我们要让多个组件复用一个基于状态的逻辑公共方法:

1.使用高阶组件

javascript">import { Table } from 'antd'
import server from './server'

function useTable(server) {
  return function (WrappedComponent) {
    return class HighComponent extends React.Component {
      state = {
        tableProps: xxx, 
      };
      render() {
        const { tableProps } = this.state;
        return <WrappedComponent tableProps={tableProps} />;
      }
    };
  };
}

@useTable(server)
class App extends Component{
  render(){
    const { tableProps } = this.props;
    return (
      <Table 
        columns={[...]}
      
        {...tableProps}
      />
    )
  }
}

2.使用Hooks

javascript">import { Table } from 'antd'
import server from './api'

function useTable(server) {
  const [tableProps, setTableProps] = useState(xxx);
  return tableProps;
}

function App {
    const { tableProps } = useTable();
    return (
      <Table 
        columns={[...]}
      
        {...tableProps}
      />
    )
}

使用Hooks可以减少组件树的层级,防止组件深度嵌套,同时代码也更少更简洁。


http://www.niftyadmin.cn/n/5158204.html

相关文章

上海亚商投顾:创业板指放量涨3.26% 两市近4500股飘红

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 沪指昨日高开后展开震荡&#xff0c;深成指涨超2%&#xff0c;创业板指大涨超3%&#xff0c;宁德时代涨超5%。…

在cocos create中如何从b文件调用到a文件里用CC.resource.load动态加载的图集

可以使用回调函数或事件来在b文件中调用a文件中动态加载的图集。 假设你的a文件中有如下代码&#xff1a; let self this; cc.resources.load("atlas/testAtlas", cc.SpriteAtlas, function (err, atlas) {if (err) {cc.error(err.message || err);return;}// 你可…

【无标题】放大放大放大

问题的关键&#xff0c;是长久以来我们已失去了生活的共识。无论是价值观的还是生活习惯的。 1、首先是对于责任的共识。既然结婚了&#xff0c;就有为家庭做出贡献的责任。一方面是要有赚钱&#xff0c;一方面是要家里的环境整洁、小孩有人陪伴和指导。总要在一个方面或所有方…

户外拉杆音箱大功率升压芯片 12.6V升压18V 3A 外围简单

SC3671 是一款专为升压、升降压开关电源设计的专用 DC-DC 控制器芯片。 SC3671 典型应用支持 5-35V 输入电压范围。通过扩展输入供电&#xff0c;也可以支持 100V 以上的输入电压范围。芯片采用固定频率的 PWM 控制方式&#xff0c;并在轻载条件下自动降频提高转换效率。芯片…

lazarus:不安装任何驱动,直接使用csv文件作为数据集

目录 1 简介 2 需要的窗体控件很简单 3 定义字段并插入几条记录 4 其他操作 4.1 数据集保存为csv文件 4.2 清空数据 4.3 加载csv文件 5 运行程序 6 导出文件 1 简介 在某些数据操作需求特别简单的情况下&#xff0c;我们希望不要安装任何数据库&#xff0c;甚至连一个…

【双指针+简化去重操作】【int运算溢出】Leetcode 18 四数之和

【双指针简化去重操作】【int运算范围】Leetcode 18 四数之和 解法1 仍然用双指针法 就是在三数求和的基础上扩展一个外层循环 ----------------------题目链接---------------------- ----------------------解析链接---------------------- 解法1 仍然用双指针法 就是在三数…

详解MES系统在质检管理中的多角度应用

MES系统的质检管理是指在制造过程中&#xff0c;利用MES系统的功能和工具来规划、执行和监控质检活动&#xff0c;以确保产品的质量符合预期标准和客户要求的管理过程。 1. 质检计划和标准制定&#xff1a; MES系统可以帮助企业制定质检计划&#xff0c;并定义质量标准和要求…

护眼灯作用大吗?五款没有危害的护眼台灯推荐

可以肯定的是&#xff0c;护眼灯一般可以达到护眼的效果。 看书和写字时&#xff0c;光线应适度&#xff0c;不宜过强或过暗&#xff0c;护眼灯光线较柔和&#xff0c;通常并不刺眼&#xff0c;眼球容易适应&#xff0c;可以防止光线过强或过暗导致的用眼疲劳。如果平时生活中…