前端面试重要代码内容之 hooks 实现¶
总结于2025.10
这些是本人在面试的时候总结的React hooks实现相关知识,加*号的是个人认为比较重要的。因为一开始是总结给自己看的,可能部分写法比较草率。如果你认为其中有错误或需要补充,请联系我~
useFetch*¶
import { useState, useEffect } from 'react';
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
// 用于返回给外部的 Promise,支持 then/catch
const fetchPromise = new Promise((resolve, reject) => {
useEffect(() => {
// 只有 url 存在时才发起请求
if (!url) {
setLoading(false);
setError(new Error('URL is required'));
reject(new Error('URL is required'));
return;
}
const fetchData = async () => {
setLoading(true);
setError(null);
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error: ${response.status}`);
}
const result = await response.json();
setData(result);
resolve(result); // 成功时 resolve
} catch (err) {
setError(err);
reject(err); // 出错时 reject
} finally {
setLoading(false);
}
};
fetchData();
}, [url]); // 依赖 url,url 变化会重新请求
});
// 返回数据、加载状态、错误,以及一个 Promise(支持 then/catch)
return {
data,
loading,
error,
promise: fetchPromise, // 可以用 .then / .catch 处理这个 Promise
};
}
usePrevious¶
import { useRef, useEffect } from 'react';
function usePrevious(value) {
const ref = useRef();
useEffect(() => { // useEffect是渲染完成后才会执行的
ref.current = value; // 在每次渲染后,将当前的 value 存入 ref
}, [value]); // 仅在 value 变化时触发
return ref.current; // 返回上一次的 value(即 ref.current)
}
useRequest¶
import { useState, useEffect, useCallback } from 'react';
// 请求缓存:以请求参数的 JSON string 作为 key
const requestCache = new Map();
function useRequest(requestFn, params) {
const [loading, setLoading] = useState(false);
const [data, setData] = useState(null);
const [error, setError] = useState(null);
// 将参数序列化为字符串作为缓存的 key
const cacheKey = JSON.stringify(params);
// 发起请求的核心逻辑
const doRequest = useCallback(async () => {
setLoading(true);
setError(null);
try {
// 检查缓存中是否存在当前参数的请求结果
if (requestCache.has(cacheKey)) {
const cached = requestCache.get(cacheKey);
setData(cached);
setLoading(false);
return cached; // 直接返回缓存,不重复请求
}
// 没有缓存,发起实际请求
const result = await requestFn(...(Array.isArray(params) ? params : [params]));
// 更新缓存
requestCache.set(cacheKey, result);
// 更新状态
setData(result);
return result;
} catch (err) {
setError(err);
throw err; // 可以被外部 .catch 捕获
} finally {
setLoading(false);
}
}, [requestFn, params, cacheKey]);
// 手动刷新:清空缓存并重新请求(或者可以选择保留缓存但依然请求最新)
const refresh = useCallback(() => {
// 可选:是否清除该 key 的缓存,这里我们选择刷新时仍然请求,但更新缓存
return doRequest();
}, [doRequest]);
// 监听 params 变化时自动执行请求
useEffect(() => {
if (params != null) {
doRequest();
}
}, [params, doRequest]);
return [loading, data, error, refresh];
}
¶
- site: Muzibing's website owner: Muzibing url: https://muzibing.github.io/ desc: "🎓 B.Eng. in CS from ZJU | 🛠️ Front-end Developer at Meituan now" image: https://github.com/Muzibing/Muzibing.github.io/blob/master/img/qhqq.jpg color: "#5486e9"