React自定义Hook中检测JSON指定key及代码优化问询
问题解答
一、判断keyName键是否存在的方法
你提到的console.log('keyName' in obj)完全可行,除此之外还有几种常用方案:
obj.hasOwnProperty('keyName'):仅检查对象自身属性,不会遍历原型链,适合明确要排除继承属性的场景obj.keyName !== undefined:简单直接,但如果键存在但值为undefined时会误判,需根据实际业务场景选择
二、代码优化与重构建议
1. 修复重复解析JSON的致命问题
Response对象的body只能被读取一次,你当前代码里调用了两次await response.json(),第二次调用会返回空对象或直接报错。必须复用已解析好的obj变量:
const fetchResponse = async () => { const response = await fetch(url); console.log(response); const obj = await response.json(); // 仅解析一次 if (response.ok) { console.log(obj); // 直接复用已解析的obj // 这里加入keyName的判断逻辑 setIsValid('keyName' in obj); } else { setIsValid(false); } return response; };
2. 补全useEffect依赖项
当前useEffect的依赖数组为空,但内部用到了url参数,这会导致url变化时无法重新触发请求,必须把url加入依赖:
useEffect(() => { // ... 内部请求逻辑 }, [url]);
3. 添加异常捕获逻辑
fetch在网络故障、跨域等场景下会抛出错误,当前代码没有处理这些异常,需要补充try/catch:
const fetchResponse = async () => { try { const response = await fetch(url); const obj = await response.json(); setIsValid(response.ok && 'keyName' in obj); } catch (error) { console.error('请求失败:', error); setIsValid(false); } };
4. 处理组件卸载时的请求中断
组件卸载时如果请求还在进行,会触发setState警告,需要用AbortController主动取消请求:
useEffect(() => { const controller = new AbortController(); const signal = controller.signal; const fetchResponse = async () => { try { const response = await fetch(url, { signal }); // 传入中断信号 const obj = await response.json(); setIsValid(response.ok && 'keyName' in obj); } catch (error) { // 忽略主动取消的错误 if (error.name !== 'AbortError') { console.error('请求失败:', error); setIsValid(false); } } }; fetchResponse(); return () => controller.abort(); // 组件卸载时中断请求 }, [url]);
5. 优化状态语义与初始值
- 初始状态设为
false容易让调用者误以为请求已失败,建议用undefined表示请求未完成状态,或者拆分出加载状态:
// 方案1:用undefined表示未完成 const [isValid, setIsValid] = useState<boolean | undefined>(undefined); // 方案2:拆分加载与结果状态 const [isLoading, setIsLoading] = useState(true); const [isValid, setIsValid] = useState(false);
- Hook命名可以更贴合功能,比如改为
useHasResponseKey,让调用者一眼就能明白其作用。
6. 移除无用代码
fetchResponse().then((res) => res);这段代码没有任何实际作用,直接改为fetchResponse();即可。
内容的提问来源于stack exchange,提问作者meez
相关产品推荐
相关产品推荐

