react18【系列实用教程】Hooks (useState,useReducer,useRef,useEffect,useContext,useMemo,useCallback,自定义 Hook )

简介: react18【系列实用教程】Hooks (useState,useReducer,useRef,useEffect,useContext,useMemo,useCallback,自定义 Hook )

Hook 是什么?

React 中,以“use”开头的函数都被称为 Hook。

Hook 是实现特殊功能的函数,只在 React 渲染时有效,只能在组件或自定义 Hook 的最顶层调用。

React 内置了很多 Hook ,你也可以自定义 Hook。

Hook 的使用规范

1.只能在 react 函数组件和自定义 Hook 中使用

2.只能在顶层使用,不能在判断(如 if 语句)/ 循环(如 for 语句)中使用

因为 Hooks 严重依赖于调用顺序,在组件挂载(render)和更新(re-render)时,Hooks 的调用顺序必须保持一致,若在判断/循环语句中使用,则可能引发 Hooks 的调用顺序发生改变,导致 Hooks 内的逻辑错乱(如响应式变量的值赋值给了其他变量)。

Hook 实现组件逻辑复用的好处

  • 完全符合 Hooks 原有规则,易理解记忆
  • 变量作用域明确
  • 不会产生组件嵌套

其他方式实现组件逻辑复用的缺陷

Mixins(已废弃)的缺陷

与 vue 相同

  • 变量作用域来源不清
  • 属性重名
  • Mixins 引入过多会导致顺序冲突

高阶组件 HOC 的缺陷

高阶组件 HOC 是 react 的 class 组件实现组件逻辑复用的一种方式

  • 组件层级嵌套过多,不易渲染,不易调试
  • HOC 会劫持 props,必须严格规范,容易出现疏漏

Render Prop 的缺陷

Render Prop 是 react 的 class 组件实现组件逻辑复用的另一种方式

  • 学习成本高,不易理解
  • 只能传递纯函数,而默认情况下纯函数功能有限

React 的内置 Hook

useState

详见 https://blog.csdn.net/weixin_41192489/article/details/138664118


useReducer

详见 https://blog.csdn.net/weixin_41192489/article/details/138863860


useRef

详见 https://blog.csdn.net/weixin_41192489/article/details/138952934


useEffect

详见 https://blog.csdn.net/weixin_41192489/article/details/138706946


useContext

详见 https://blog.csdn.net/weixin_41192489/article/details/138700487


useMemo

详见 https://blog.csdn.net/weixin_41192489/article/details/138909376


useCallback

详见 https://blog.csdn.net/weixin_41192489/article/details/138911123

自定义 Hook

即根据自己的业务需要编写use开头的函数,实现逻辑封装和复用。

自定义 Hook 的步骤

  1. 新建文件 myHooks.js,存放所有自定义的 hook
  2. 将可复用的逻辑封装成use开头的函数,以对象或数组的数据格式 return 组件中需要用到的变量和函数
  3. 对外导出自定义的 hook
  4. 在目标组件中导入自定义的 hook
  5. 通过对象/数组解构赋值(与自定义 hook 中return 的数据格式对应),使用自定义的 hook

范例1 - 切换显示隐藏 useToggle

myHooks.js

import { useState } from "react";

// 切换显示隐藏
export const useToggle = (initValue) => {
  const [show, setShow] = useState(initValue);

  function toggleShow() {
    setShow(!show);
  }

  return [show, toggleShow];
};

index.jsx

import { useToggle } from "./myHooks.js";

function Demo() {
  const [showTitle, toggleShowTitle] = useToggle(true);
  const [showContent, toggleShowContent] = useToggle(false);

  return (
    <>
      {showTitle && <h1>标题</h1>}
      <button onClick={toggleShowTitle}>显示/隐藏标题</button>

      <div>
        {showContent && <p>段落</p>}
        <button onClick={toggleShowContent}>显示/隐藏内容</button>
      </div>
    </>
  );
}

export default Demo;

范例2 - 组件挂载时请求接口数据 useGetInitData

myHooks.js

import { useState, useEffect } from "react";
import axios from "axios";

// 访问接口
export const useGetInitData = (url) => {
  const [data, setData] = useState([]);
  useEffect(() => {
    async function getData() {
      const res = await axios.get(url);
      setData(res.data);
    }
    getData();
  }, []);

  return [data, setData];
};

index.jsx

import { useGetInitData } from "./myHooks.js";

function Demo() {
  const [list, setList] = useGetInitData("http://localhost:3000/dataList");

  function clearList() {
    setList([]);
  }

  return (
    <>
      {list.map((item) => (
        <div key={item.id}>{item.title}</div>
      ))}
      <button onClick={clearList}>清空</button>
    </>
  );
}

export default Demo;

范例3 - url 改变时请求接口数据 useAxios

useAxios.js

import { useState, useEffect } from 'react'
import axios from 'axios'

// 封装 axios 发送网络请求的自定义 Hook
function useAxios(url) {
    const [loading, setLoading] = useState(false)
    const [data, setData] = useState()
    const [error, setError] = useState()

    useEffect(() => {
        // 利用 axios 发送网络请求
        setLoading(true)
        axios.get(url) // 发送一个 get 请求
            .then(res => setData(res))
            .catch(err => setError(err))
            .finally(() => setLoading(false))
    }, [url])

    return [loading, data, error]
}

export default useAxios

使用

import useAxios from './useAxios'
 
 const url = 'http://localhost:3000/'
 // 数组解构
 const [loading, data, error] = useAxios(url)

 if (loading) return <div>loading...</div>

 return error
     ? <div>{JSON.stringify(error)}</div>
     : <div>{JSON.stringify(data)}</div>

范例4 - 实时获取鼠标坐标 useAxios

useMousePosition.js

import { useState, useEffect } from 'react'

function useMousePosition() {
    const [x, setX] = useState(0)
    const [y, setY] = useState(0)

    useEffect(() => {
        function mouseMoveHandler(event) {
            setX(event.clientX)
            setY(event.clientY)
        }

        // 绑定事件
        document.body.addEventListener('mousemove', mouseMoveHandler)

        // 解绑事件
        return () => document.body.removeEventListener('mousemove', mouseMoveHandler)
    }, [])

    return [x, y]
}

export default useMousePosition

使用

import useMousePosition from './useMousePosition'
 
const [x, y] = useMousePosition()
return <div>
    <p>鼠标位置 {x} {y}</p>
</div>

目录
相关文章
|
2月前
|
人工智能 自然语言处理 前端开发
SpringBoot + 通义千问 + 自定义React组件:支持EventStream数据解析的技术实践
【10月更文挑战第7天】在现代Web开发中,集成多种技术栈以实现复杂的功能需求已成为常态。本文将详细介绍如何使用SpringBoot作为后端框架,结合阿里巴巴的通义千问(一个强大的自然语言处理服务),并通过自定义React组件来支持服务器发送事件(SSE, Server-Sent Events)的EventStream数据解析。这一组合不仅能够实现高效的实时通信,还能利用AI技术提升用户体验。
236 2
|
1月前
|
前端开发
深入探索React Hooks:从useState到useEffect
深入探索React Hooks:从useState到useEffect
24 3
|
1月前
|
前端开发 JavaScript
深入探索React Hooks:从useState到useEffect
深入探索React Hooks:从useState到useEffect
|
3月前
|
前端开发
React给antd中TreeSelect组件左侧加自定义图标icon
本文介绍了如何在React中为Ant Design的TreeSelect组件的每个树节点添加自定义图标,并解决了因缺少key属性而导致的警告问题,展示了如何通过递归函数处理treeData数据并为每个节点添加图标。
174 2
React给antd中TreeSelect组件左侧加自定义图标icon
|
2月前
|
前端开发 JavaScript CDN
React 教程
10月更文挑战第6天
50 3
|
2月前
|
存储 前端开发 JavaScript
React useState 和 useRef 的区别
本文介绍了 React 中 `useState` 和 `useRef` 这两个重要 Hook 的区别和使用场景。`useState` 用于管理状态并在状态变化时重新渲染组件,适用于表单输入、显示/隐藏组件、动态样式等场景。`useRef` 则用于在渲染之间保持可变值而不触发重新渲染,适用于访问 DOM 元素、存储定时器 ID 等场景。文章还提供了具体的代码示例,帮助读者更好地理解和应用这两个 Hook。
58 0
|
3月前
|
前端开发
React中函数式Hooks之useState的使用
本文介绍了React中函数式组件的Hooks——`useState`的使用方法。`useState`允许在函数式组件中使用状态,它返回一个数组,其中包含当前状态的值和更新该状态的函数。文章通过示例代码展示了如何声明状态变量和更新状态变量,包括对数值和对象状态的更新。此外,还展示了如何通过点击按钮触发状态更新,实现交互功能。
43 1
|
2月前
|
前端开发 JavaScript API
自定义React Hooks综合指南
本文介绍了React Hooks及其在组件开发中的作用,重点讲解了自定义Hook的创建和使用方法。通过实例展示了如何创建`useWindowWidth`、`useFetch`和`useForm`等自定义Hook,并分享了使用自定义Hook的最佳实践。文章强调了自定义Hook在提高代码复用性和组件可维护性方面的重要性。
78 0
|
1月前
|
前端开发 JavaScript 开发者
颠覆传统:React框架如何引领前端开发的革命性变革
【10月更文挑战第32天】本文以问答形式探讨了React框架的特性和应用。React是一款由Facebook推出的JavaScript库,以其虚拟DOM机制和组件化设计,成为构建高性能单页面应用的理想选择。文章介绍了如何开始一个React项目、组件化思想的体现、性能优化方法、表单处理及路由实现等内容,帮助开发者更好地理解和使用React。
78 9
|
2月前
|
前端开发
深入解析React Hooks:构建高效且可维护的前端应用
本文将带你走进React Hooks的世界,探索这一革新特性如何改变我们构建React组件的方式。通过分析Hooks的核心概念、使用方法和最佳实践,文章旨在帮助你充分利用Hooks来提高开发效率,编写更简洁、更可维护的前端代码。我们将通过实际代码示例,深入了解useState、useEffect等常用Hooks的内部工作原理,并探讨如何自定义Hooks以复用逻辑。