React自定义useFetch仅在表单提交时触发请求问题排查
代码问题梳理
- useFetch的依赖项传入错误:你当前给useFetch传的第三个参数是
setIp(状态修改函数,引用永远不变),但实际需要监听的是Ip状态本身——只有表单提交时Ip才会更新,这才是触发请求的正确依赖。
- useFetch的依赖项传入错误:你当前给useFetch传的第三个参数是
- 初始渲染自动触发请求:useEffect默认会在组件挂载时执行一次,此时
Ip为空值,所以返回null。需要加判断逻辑,仅当Ip有有效值时才发起请求。
- 初始渲染自动触发请求:useEffect默认会在组件挂载时执行一次,此时
- 多余的解构与参数误用:useFetch的返回值中没有
dep字段,你在Header组件里的解构属于无效代码,也不会影响请求逻辑。
- 多余的解构与参数误用:useFetch的返回值中没有
- useEffect依赖不全:useFetch内部的useEffect只写了
dep作为依赖,但实际用到了url、options,不符合React依赖规则,容易引发逻辑bug。
- useEffect依赖不全:useFetch内部的useEffect只写了
- 错误场景漏处理:请求报错时没有关闭加载状态,会导致页面一直显示加载中。
修正后的代码
1. useFetch.js 修正
import { useState, useEffect } from 'react'; export const useFetch = (url, options, trigger) => { const [response, setResponse] = useState(null); const [error, setError] = useState(null); const [isLoading, setIsLoading] = useState(false); useEffect(() => { // 新增判断:trigger有有效值才发起请求,避免初始渲染空请求 if(!trigger) return; const fetchData = async () => { setIsLoading(true); try { const res = await fetch(url, options); const json = await res.json(); setResponse(json); setIsLoading(false); } catch (error) { setError(error); setIsLoading(false); } }; fetchData(); }, [trigger, url, options]); // 补全所有用到的依赖 return { response, error, isLoading }; };
2. Header组件修正
import { useState } from 'react'; import { FaArrowRight } from 'react-icons/fa'; import React from 'react'; import { Form, FormInput, Head, HeadLine, Button } from './Header.elements'; import { useFetch } from '../../useFetch'; const Header = () => { const [value, setValue] = useState(''); const [Ip, setIp] = useState(''); // 初始设为空,避免初始无效请求 const API_KEY = 'at_xtpIidIz9vUqEzBODaUwtVRXf'; // 只有Ip更新时URL才会更新 const URL = `https://geo.ipify.org/api/v1?apiKey=${API_KEY}&ipAddress=${Ip}`; const handleSubmit = (e) => { e.preventDefault(); // 提交时才更新Ip,触发useFetch请求 setIp(value.trim()); }; // 第三个参数传Ip作为请求触发条件,去掉多余的dep解构 const { isLoading, response } = useFetch(URL, {}, Ip); console.log(response); const handleChange = (e) => { setValue(e.target.value); }; return ( <> <Head> <HeadLine>IP Address Tracker</HeadLine> <Form onSubmit={handleSubmit}> <FormInput onChange={handleChange} value={value} placeholder='Search for any IP address or Domain' /> <Button type='submit' disabled={isLoading}> <FaArrowRight /> </Button> </Form> </Head> </> ); }; export default Header;
修正后仅当点击提交按钮更新Ip状态时才会发起请求,输入内容时仅修改输入框绑定的value状态,不会触发请求,初始渲染也不会发起无效空请求。
内容的提问来源于stack exchange,提问作者shouravRahman
相关产品推荐
相关产品推荐

