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

React状态需点击两次按钮才更新,接口请求延迟问题排查

React组件首次搜索请求失败,二次点击才成功的解决方法

问题描述

从Express API获取数据时,后端接口运行正常,但前端存在以下问题:修改input内容后调用数据获取函数,状态更新有延迟,首次点击搜索按钮时请求失败,第二次点击才成功。

组件代码

import React, { useState, useEffect } from 'react';
import UsersList from './UsersList.js';

function SearchBox() {

    const [input, setInput] = useState("");
    const [githubUserResult, setGithubUserResult] = useState([]);
    const [gitlabUserResult, setGitlabUserResult] = useState([]);
    const [isLoaded, setIsloaded] = useState(false);
    const [error, setError] = useState(null);

    const handleInputChange = (e) => {
        setInput(e.target.value);
    }

    const searchUser = async (e) => {
        e.preventDefault();
        searchUserOnGithub(input);
        searchUserOnGitLab(input);
        setIsloaded(true);
    }

    const searchUserOnGithub = async (username) => {
       await fetch(`/api/github/userinfo/${username}`, {
            method: "GET", headers: {
                "Content-Type": "application/json",
            }
        })
            .then(res => res.json())
            .then(
                (result) => {
                    setGithubUserResult(result);
                    console.log(githubUserResult);
                },
                (error) => {
                    setError(error)
                })
    }

    const searchUserOnGitLab = async (username) => {
       await fetch(`/api/gitlab/userinfo/${username}`, {
            method: "GET", headers: {
                "Content-Type": "application/json",
            }
        })
            .then(res => res.json())
            .then(
                (result) => {
                    setGitlabUserResult(result);
                    console.log(gitlabUserResult);
                },
                (error) => {
                    setError(error)
                })
    }

    if (error) {
        return <div>Error: {error.message}</div>;
    }return (
        <div className='search-container'>
            <form>
                <input type="text" onChange={handleInputChange} />
                <button type="button" onClick={searchUser} >Search</button>
            </form>
            <h3>github</h3><br />
            {/*isLoaded ? <UsersList users={githubUserResult} />: ''*/}
            <h3>gitLab</h3><br />
            {/*isLoaded ? <UsersList users={gitlabUserResult} /> : ''*/}
        </div>
    )

}

export default SearchBox;

问题原因

  1. Input为不受控组件:代码中的input只绑定了onChange事件更新状态,但未绑定value={input},导致输入框实际值与React状态input不同步,首次点击时传递给接口的username是初始空值,第二次点击才拿到之前输入的内容。
  2. 异步代码写法混乱:混合使用await和.then,且searchUser中未等待异步请求完成就设置isLoaded,状态更新逻辑混乱。
  3. setState异步特性误解:在setGithubUserResult后直接console.log(githubUserResult),此时打印的是旧状态,无法查看更新后的数据。

修复方案

1. 将Input改为受控组件

给input添加value属性绑定到input状态,确保输入值与状态完全同步:

<input type="text" value={input} onChange={handleInputChange} />

2. 优化异步请求逻辑

统一使用async/await语法,避免混合then,同时在searchUser中等待所有请求完成后再更新加载状态:

const searchUser = async (e) => {
    e.preventDefault();
    setError(null); // 重置错误状态
    try {
        // 并行发起两个请求,等待全部完成
        await Promise.all([
            searchUserOnGithub(input),
            searchUserOnGitLab(input)
        ]);
        setIsloaded(true);
    } catch (err) {
        setError(err);
    }
}

3. 重构单个请求函数

去掉多余的await和then混合写法,添加响应状态检查,完善错误处理:

const searchUserOnGithub = async (username) => {
    const res = await fetch(`/api/github/userinfo/${username}`, {
        method: "GET",
        headers: {
            "Content-Type": "application/json",
        }
    });
    // 检查响应是否成功
    if (!res.ok) {
        throw new Error(`GitHub请求失败: ${res.status}`);
    }
    const result = await res.json();
    setGithubUserResult(result);
}

const searchUserOnGitLab = async (username) => {
    const res = await fetch(`/api/gitlab/userinfo/${username}`, {
        method: "GET",
        headers: {
            "Content-Type": "application/json",
        }
    });
    if (!res.ok) {
        throw new Error(`GitLab请求失败: ${res.status}`);
    }
    const result = await res.json();
    setGitlabUserResult(result);
}

4. 正确查看状态更新结果

由于setState是异步的,直接在set之后打印无法获取新状态,使用useEffect监听状态变化:

useEffect(() => {
    console.log("GitHub用户结果更新:", githubUserResult);
}, [githubUserResult]);

useEffect(() => {
    console.log("GitLab用户结果更新:", gitlabUserResult);
}, [gitlabUserResult]);

总结

核心问题是input未使用受控组件模式,导致状态与输入值不同步。修复后,输入内容会实时同步到React状态,首次点击就能传递正确的username发起请求,同时优化后的异步代码逻辑更清晰,错误处理更完善。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 04:01:39