欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 手游 > 0303hooks-react-仿低代码平台项目

0303hooks-react-仿低代码平台项目

2025/6/17 20:34:20 来源:https://blog.csdn.net/gaogzhen/article/details/147023964  浏览:    关键词:0303hooks-react-仿低代码平台项目

文章目录

    • 1. 副作用
    • 2.其他内置hooks
      • 2.1 useEffect
      • 2.2 useRef
      • 2.3useMemo
      • 2.4 useCallback
    • 3.自定义hooks
    • 4. 第三方hooks
    • 5. hooks使用原则
    • 6. hooks闭包陷阱
    • 7. 总结
    • 结语

1. 副作用

  • 当组件渲染完成时,加载一个Ajax网络请求
  • 当某个state更新时,加载一个Ajax网络请求

示例:

const List2: FC = () => {console.log("加载Ajax网络请求。。。");...	

控制台如下图所示:在这里插入图片描述

分析:函数式组件,任何state更新,都会重新执行函数;组件初次渲染,也会执行函数。

解决这种情况,通过如下其他hooks完成。

2.其他内置hooks

2.1 useEffect

  • useEffect用法

解决“当组件渲染完成时,加载一个Ajax网络请求”问题,如下所示:

  useEffect(() => {console.log("渲染完成");}, []);
// 格式
useEffect(setup, dependencies?)
useEffect(func, [])

组件渲染完成,执行一次。

  • 参数分析:

    • func:函数

    • []:依赖于…触发,默认”空“当前组件。

  • useEffect执行只依赖于[]中指定的变量,可以是多个,任一一个变量更新,都触发函数执行。示例如下

      useEffect(() => {console.log("渲染完成");}, []);useEffect(() => {console.log("questionList change");}, [questionList]);
    
    • 执行组件增、改、删,打印questionList change在这里插入图片描述
  • 组件销毁时触发useEffect,QuestionCard.tsx如下

      useEffect(() => {console.log("QuestionCard mounted");return () => {console.log("QuestionCard unmounted " + id);};}, []);
    
    • 控制台打印如下所示:在这里插入图片描述
  • useEffect监听react组件的声明周期:创建、更新、销毁等。

  • useEffect组件执行创建-销毁-在创建原因:从v18版本开始,在开发环境下会执行该过程;在生成环境中只执行一次。

    yarn build
    把打包好的文件放置在nginx配置的web路径下
    
    • 如下图所示:在这里插入图片描述

2.2 useRef

在 React 开发中,开发者常常需要直接操作 DOM 元素或存储临时数据,但 React 的状态管理机制(如 useState)有时无法满足这些需求。这时,一个名为 useRef 的 Hook 就像一位灵活的“中间人”,在虚拟 DOM 与真实 DOM 之间架起了一座桥梁。本文将深入探讨 useRef 的核心原理、使用场景及进阶技巧,帮助开发者高效利用这一工具解决实际问题。

  • 什么是 useRef?

useRef 是 React 提供的一个 Hook,用于创建可变的引用(reference),其核心特性是:

  1. 不会触发组件重渲染:修改 useRef 的值不会导致组件重新渲染;
  2. 直接访问 DOM 元素:通过 ref 属性绑定到 DOM 元素,获取其真实引用;
  3. 存储临时数据:适合保存不需要触发 UI 更新的临时变量。

示例:

import { FC, useRef } from "react";const Demo: FC = () => {const inputRef = useRef<HTMLInputElement>(null);function selectInput() {const inputEle = inputRef.current;inputEle && inputEle.select();}return (<div><input ref={inputRef} defaultValue="hello world" /><button onClick={selectInput}> 点击选中</button></div>);
};export default Demo;

在这里插入图片描述

  • 一般用于操作DOM
  • 也可传入普通JS变量,单更新不会触发rerender

2.3useMemo

  • 函数组件,每次state更新都会重新执行函数
  • useMemo可以缓存数据,不用每次执行函数都重新生成
  • 可用于计算量较大的场景,缓存提高性能
import { FC, useState, useMemo } from "react";
const Demo: FC = () => {console.log("demo...");const [num1, setNum1] = useState(10);const [num2, setNum2] = useState(20);const [text, setText] = useState("hello");const sum = useMemo(() => {console.log("sum use memo ");return num1 + num2;}, [num1, num2]);return (<><p>{sum} </p><p>{num1}<buttononClick={() => {setNum1(num1 + 1);}}>add num1</button></p><p>{num2}<buttononClick={() => {setNum2(num2 + 1);}}>add num2</button></p><div><input onChange={(e) => setText(e.target.value)} value={text} /></div></>);
};export default Demo;

在这里插入图片描述

2.4 useCallback

  • 和useMemo作用一样,专门用于缓存函数

示例:

import { FC, useState, useCallback } from "react";const Demo: FC = () => {const [text, setText] = useState("hello");const fn1 = () => console.log("fn1 text ", text);const fn2 = useCallback(() => {console.log("fn2 text ", text);}, [text]);return (<><div><button onClick={fn1}>fn1</button><hr /><button onClick={fn2}>fn2</button></div><div><input onChange={(e) => setText(e.target.value)} value={text} /></div></>);
};export default Demo;

缓存,性能优化,提示时间效率。

3.自定义hooks

  • 内置hooks保证基础的功能
  • 内置hooks灵活配合,实现业务功能
  • 抽离公共部分,自定义hooks或者第三方hooks-复用代码

代码演示1:修改网页标题

UseTitle.ts

import { useEffect } from "react";function useTitle(title: string) {useEffect(() => {document.title = title;}, []);
}export default useTitle;

App.tsx

import useTitle from "./hooks/UseTitle";function App() {useTitle("自定义标题1");return (<></>);
}export default App;

在这里插入图片描述

代码演示2:获取鼠标位置

useMouse.ts

import { useState, useEffect } from "react";// 获取鼠标位置,自定义hooks
function useMouse() {const [x, setX] = useState(0);const [y, setY] = useState(0);// 鼠标事件处理const mouseEventHandler = (e: MouseEvent) => {setX(e.clientX);setY(e.clientY);};useEffect(() => {// 监听鼠标事件window.addEventListener("mousemove", mouseEventHandler);//组件销毁时,一定要解绑DOM事件(不解绑,可能出现内存泄露问题)return () => {// 解绑鼠标事件,与绑定时参数相同window.removeEventListener("mousemove", mouseEventHandler);};}, []);return { x, y };
}export default useMouse;

App.tsx

import useMouse from "./hooks/useMouse";function App() {const { x, y } = useMouse();return (<><p>鼠标位置:{x} {y}</p></>);
}export default App;

效果如下图所示:在这里插入图片描述

代码演示3:模拟异步获取数据

useGetInfo.ts

import { useState, useEffect } from "react";// 异步获取信息
function getInfo(): Promise<string> {return new Promise((resolve) => {setTimeout(() => {resolve(new Date().toString());}, 1500);});
}const useGetInfo = () => {const [loading, setLoading] = useState(true);const [info, setInfo] = useState("");useEffect(() => {getInfo().then((info) => {setLoading(false);setInfo(info);});}, []);return { loading, info };
};export default useGetInfo;

App.tsx

import useGetInfo from "./hooks/useGetInfo";function App() {const { loading, info } = useGetInfo();return (<><div>{loading ? "加载中" : info}</div></>);
}export default App;

效果如下图所示:在这里插入图片描述

4. 第三方hooks

常用第三方hooks:文档地址参考下面链接2和链接3

  • ahooks
  • react-use

以ahooks为例,演示:修改网页标题

import { useTitle } from "ahooks";function App() {useTitle("自定义标题2");return (<></>);
}export default App;

演示:获取鼠标位置

import { useMouse } from "ahooks";function App() {const { clientX, clientY } = useMouse();return (<><p>鼠标位置:{clientX} {clientY}</p></>);
}export default App;

5. hooks使用原则

  • 使用useXxx格式命名
  • 只能在两个地方调用hook:组件内,其他hook内。
  • 必须保证每次的调用顺序一致(不能放在if for内部)

6. hooks闭包陷阱

  • 当异步函数获取state时,可能不是当前最新的state
  • 可以使用useRef解决

演示示例:

Cloususe.tsx

import { FC, useState, useRef, useEffect } from "react";const Demo: FC = () => {const [count, setCount] = useState(0);// 累加function add() {setCount(count + 1);}// 打印countfunction printCount() {setTimeout(() => {console.log(count);}, 2000);}return (<><p>闭包陷阱</p><div><p>{count}</p><button onClick={add}>累加</button><button onClick={printCount}>打印</button></div></>);
};export default Demo;

App.tsx

import ClosureTrap from "./ClosureTrap";function App() {return (<><ClosureTrap /></>);
}export default App;

效果如下图所示:在这里插入图片描述

解决方案:

Clousure.tsx

import { FC, useState, useRef, useEffect } from "react";const Demo: FC = () => {const [count, setCount] = useState(0);const countRef = useRef(0);useEffect(() => {countRef.current = count;}, [count]);// 累加function add() {setCount(count + 1);}// 打印countfunction printCount() {setTimeout(() => {console.log(countRef.current);}, 2000);}return (<><p>闭包陷阱</p><div><p>{count}</p><button onClick={add}>累加</button><button onClick={printCount}>打印</button></div></>);
};export default Demo;

效果如下图所示:在这里插入图片描述

7. 总结

目标:

  • 学会内置hooks
  • 学会自定义hooks
  • 学会使用第三方hooks

知识点:

  • 自定义hooks

    • useState

      • Immer:state的不可变数据
    • useEffect

    • useRef

    • useMemo

    • useCallback

  • 第三方hooks

    • ahooks

    • react-use

  • 闭包陷阱

注意事项:

  • hooks是React最重要的内容之一
  • 初学者很难通过概念理解hooks,必须配合大量实践练习
  • hooks有很多规则,遇到错误时,先看是否违反规则

结语

❓QQ:806797785

⭐️仓库地址:https://gitee.com/gaogzhen

⭐️仓库地址:https://github.com/gaogzhen

[1]useEffect[CP/OL].

[2]ahook官网[CP/OL].

[3]github react-use[CP/OL].

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词