前端---自定义hook函数
思路: 单独的文件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)
案例一
// 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)
案例二 自定义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 变化自动重新请求
)
工作1-3年,基础知识,多看书。多跟着别人做项目,学习经验。 工作3-5年,新知识,高级知识,自己独立做项目,总结经验。尝试不同的语言。 工作5-8年,工作职位,要从设计,管理方面要求自己,可以尝试走管理路线(项目经理或cto)。 工作10年及以上, 自己做些项目,产品,尝试为创业做准备。 上大学和不上大学区别很大,上品牌大学和普通大学区别也很大,后天的努力最大。 ---无论它是在遥远的远方,还是在出发的地方、哪里有希望哪里就是我们的方向;终点、只不过是梦想起飞的地方。