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
相关产品推荐
相关产品推荐

