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

React中带依赖的useEffect为何触发初始请求?如何修复?

问题原因
  • useEffect默认执行机制:React中,带依赖项的useEffect会在组件首次挂载时强制执行一次,哪怕依赖项初始值是false。你的hasPressed初始值为false,组件挂载时effect仍会触发,此时searchByName是空字符串,就会发起无效请求。
  • 表单逻辑冲突:form内的button默认是submit类型,点击时会同时触发buttonHandler(切换hasPressed)和handleSubmit(设置hasPressed为true),导致状态混乱,且没必要同时绑定两个事件处理函数。
修复方案

1. 给effect加前置判断

在effect中增加条件,仅当hasPressed为true且输入框有内容时才发起请求,避免初始挂载和空值请求:

useEffect(() => {
    // 仅满足点击触发+输入有效时才请求
    if (hasPressed && searchByName.trim()) {
        fetch(`https://pokeapi.co/api/v2/pokemon/${searchByName}`)
            .then(response => {
                // 新增请求成功判断,避免404等错误导致的状态异常
                if (!response.ok) throw new Error('宝可梦不存在');
                return response.json();
            })
            .then(data => {
                console.log(data);
                setPokemonInfo(data);
                setHasInfo(true);
            })
            .catch(error => {
                console.error('请求失败', error);
                setHasInfo(false); // 请求失败时清空结果显示
            });
    }
}, [hasPressed, searchByName]); // 依赖项新增searchByName,确保输入更新后点击能请求最新值

2. 简化表单提交逻辑

移除button的onClick,直接在handleSubmit中处理状态变更,避免重复触发:

const handleSubmit = (e) =>{
    e.preventDefault();
    // 仅输入有效时才触发请求状态
    if (searchByName.trim()) {
        setHasPressed(true);
        console.log(searchByName);
    }
};

// 移除buttonHandler函数

// 表单内按钮修改为:
<button type="submit">搜索</button>

3. 优化状态重置逻辑

输入框内容变化时,重置结果显示状态,避免旧内容残留:

const changeHandler = (e) =>{
    setSearchByName(e.target.value);
    setHasPressed(false);
    setHasInfo(false); // 输入变化时清空之前的搜索结果
};

完整修复后代码

import { useEffect, useState } from "react";
import BasicInfo from "./BasicInfo";

export default function MainInfo(){
    const [searchByName, setSearchByName] = useState('');
    const [pokemonInfo, setPokemonInfo] = useState({});
    const [hasInfo, setHasInfo] = useState(false);
    const [hasPressed, setHasPressed] = useState(false);

    const handleSubmit = (e) =>{
        e.preventDefault();
        if (searchByName.trim()) {
            setHasPressed(true);
            console.log(searchByName);
        }
    };

    const changeHandler = (e) =>{
        setSearchByName(e.target.value);
        setHasPressed(false);
        setHasInfo(false);
    };

    useEffect(() => {
        if (hasPressed && searchByName.trim()) {
            fetch(`https://pokeapi.co/api/v2/pokemon/${searchByName}`)
                .then(response => {
                    if (!response.ok) throw new Error('宝可梦不存在');
                    return response.json();
                })
                .then(data => {
                    console.log(data);
                    setPokemonInfo(data);
                    setHasInfo(true);
                })
                .catch(error => {
                    console.error('请求失败', error);
                    setHasInfo(false);
                });
        }
    }, [hasPressed, searchByName])
    
    return(
        <div>
            <form onSubmit={handleSubmit}>
                <input 
                    type="text" 
                    name="input" 
                    value={searchByName} 
                    onChange={changeHandler}
                    placeholder="输入宝可梦名称"
                />
                <button type="submit">搜索</button>
            </form>
            {hasInfo && pokemonInfo.abilities && (
                <div>
                    <BasicInfo
                        name={pokemonInfo.name}
                        abilities={pokemonInfo.abilities}
                    />
                </div>
            )}
        </div>
    );
}

内容的提问来源于stack exchange,提问作者BC_Pants

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 17:48:20