惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

L
LangChain Blog
阮一峰的网络日志
阮一峰的网络日志
WordPress大学
WordPress大学
博客园 - 司徒正美
罗磊的独立博客
D
Docker
Last Week in AI
Last Week in AI
爱范儿
爱范儿
M
MIT News - Artificial intelligence
V
V2EX
Google DeepMind News
Google DeepMind News
小众软件
小众软件
Apple Machine Learning Research
Apple Machine Learning Research
Microsoft Security Blog
Microsoft Security Blog
T
Tailwind CSS Blog
MyScale Blog
MyScale Blog
V
Visual Studio Blog
博客园 - 叶小钗
B
Blog RSS Feed
A
About on SuperTechFans
F
Fortinet All Blogs
T
The Blog of Author Tim Ferriss
Martin Fowler
Martin Fowler
P
Proofpoint News Feed

博客园 - JavAndroidJSql

ai编程----Ai codex编程 龙虾---openClaw 配置企业微信 龙虾---openClaw龙虾安装和理解(类似Hermes 编程开源智能体) 前端--react使用 Reducer 和 Context 拓展应用和组件 前端----服务端渲染组件SSR 前端---ts语法 前端--uniapp ai---sd 模型头像生成 前端 ----form表单对齐处理 ai------代码辅助ai工具对比 ai ----语音克隆 数字人 项目相关方案 @前端----节流防抖 @前端--webpack实现原理及核心过程 @面试项目管理----总结整理 js开发过程遇到的基础问题 ai数字人相关研究 前端 -----浏览器等前端运行容器的工作原理 ios ---时间 格式 判断兼容问题 人工智能chatGPT----链接大全 ffmpeg----用法及命令使用总结
前端---自定义hook函数
JavAndroidJSql · 2025-08-23 · via 博客园 - JavAndroidJSql

思路: 单独的文件js、ts , 里面借助现有的use函数比如useState,useEffect,useCallBack

实现封装逻辑复用。

标准结构: useTest.ts/js

import {useEffect,useRef,useState,useCallback} from 'react'

export fuction useTest<T = unknown>(参数){  // T是返回类型,参数

  const [result,setResult]=useState<T | null>(null); // 定义返回的结果数据类型T统一

  useEffect (()=>{

  // 其他计算逻辑

  setResult('计算后的结果');

  },[参数变化]);

 return result     ; 

}

调用:

import { useTest } from './useTest'

 const debounced = useTest<string>(  'sd',300)

const debounced = useTest<{ items: any }>({ items: [] }300) 

案例一 

// useDebounce.ts输入防抖

import { useEffect, useMemo, useRef, useState } from 'react'

export function useDebounce<T>(value: T, delay = 300) { // T是返回类型, 括号里是参数

  const [debounced, setDebounced] = useState<T>(value)                     // 保存防抖后的值

  const timer = useRef<number | null>(null)                             // 记录定时器 id

  useEffect(() => {

    if (timer.current) window.clearTimeout(timer.current)               // 新变更来了先清除旧定时器

    timer.current = window.setTimeout(() => setDebounced(value), delay) // delay 后再真正更新

    return () => { if (timer.current) window.clearTimeout(timer.current) }

  }, [value, delay])

  return debounced                                                       // 返回稳定后的值

}

具体调用:

import { useDebounce } from './useDebounce'

 const debounced = useDebounce<string>(  'sd',300)

const debounced = useDebounce<{ items: any }>({ items: [] }, 300) 

案例二  自定义useFetch

// useFetch.ts

import { useEffect, useRef, useState, useCallback } from 'react'

/**

 * useFetch: 最小但实用的请求 Hook

 * @param url 请求地址(字符串或返回字符串的函数,便于依赖外部状态)

 * @param options fetch 的配置项(可选)

 * @param deps 触发重新请求的依赖数组(可选,默认只在 url/options 变化时请求)

 */

export function useFetch<T = unknown>(

  url: string | (() => string),

  options?: RequestInit,

  deps: any[] = []

) {

  const [data, setData] = useState<T | null>(null)               // 保存返回数据

  const [error, setError] = useState<unknown>(null)              // 保存错误

  const [loading, setLoading] = useState(false)                  // 加载状态

  const abortRef = useRef<AbortController | null>(null)          // 记录当前请求控制器

  const getUrl = useCallback(() => (typeof url === 'function' ? url() : url), [url]) // 统一拿 URL

  const fetchData = useCallback(async () => {

    // 每次请求前先取消上一次未完成的请求,避免竞态

    abortRef.current?.abort()                                    // 取消上一次

    const controller = new AbortController()                     // 新建控制器

    abortRef.current = controller                                 // 存起来以便取消

    setLoading(true)                                             // 开始加载

    setError(null)                                               // 清空错误

    try {

      const res = await fetch(getUrl(), {                        // 发起请求

        ...options,                                              // 透传外部配置

        signal: controller.signal                                // 绑定可取消信号

      })

      if (!res.ok) throw new Error(`HTTP ${res.status}`)         // 非 2xx 视为错误

      const json = (await res.json()) as T                       // 解析 JSON

      setData(json)                                              // 写入数据

    } catch (e: any) {

      if (e?.name !== 'AbortError') setError(e)                  // 被取消不算错误

    } finally {

      setLoading(false)                                          // 结束加载

    }

  }, [getUrl, options, ...deps])                                 // url/options/外部依赖变化时重建

  useEffect(() => {

    fetchData()                                                  // 首次或依赖变化时自动请求

    return () => abortRef.current?.abort()                       // 组件卸载时取消请求

  }, [fetchData])                                                // 依赖 fetchData

  const refetch = useCallback(() => {                            // 手动重新拉取

    fetchData()

  }, [fetchData])

  return { data, error, loading, refetch }                       // 导出状态与动作

}

具体调用:

import { useFetch } from './useFetch'

 const { data, error, loading, refetch } = useFetch<{ items: any[] }>(    // 指定返回类型

    () => `https://api.github.com/search/repositories?q=${encodeURIComponent(q)}`,

    { method: 'GET' },                                                     // 可选 fetch 配置

    [q]                                                                    // q 变化自动重新请求

  )