You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React自定义useFetch仅在表单提交时触发请求问题排查

代码问题梳理
    1. useFetch的依赖项传入错误:你当前给useFetch传的第三个参数是setIp(状态修改函数,引用永远不变),但实际需要监听的是Ip状态本身——只有表单提交时Ip才会更新,这才是触发请求的正确依赖。
    1. 初始渲染自动触发请求:useEffect默认会在组件挂载时执行一次,此时Ip为空值,所以返回null。需要加判断逻辑,仅当Ip有有效值时才发起请求。
    1. 多余的解构与参数误用:useFetch的返回值中没有dep字段,你在Header组件里的解构属于无效代码,也不会影响请求逻辑。
    1. useEffect依赖不全:useFetch内部的useEffect只写了dep作为依赖,但实际用到了url、options,不符合React依赖规则,容易引发逻辑bug。
    1. 错误场景漏处理:请求报错时没有关闭加载状态,会导致页面一直显示加载中。
修正后的代码

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.19 10:54:03