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

NextJS中Fetch API需按两次回车键才生效问题排查

问题:搜索框回车后需两次触发才能获取正确结果

组件预期功能:在搜索框输入内容后按下回车键,控制台打印对应JSON数据。但实际存在以下问题:

  • 首次输入内容按回车,控制台无输出,需再按一次才打印结果
  • 修改搜索内容后按回车,返回的是上一次搜索的结果,再次按回车才能获取当前搜索结果

可输入Reinforcements或Contact进行测试,原代码如下:

import { Box, Input } from "@chakra-ui/react";
import styles from "../styles/search.module.css";
import React, { useState } from "react";

export default function Search() {
  const [cardName, setCardName] = useState("");
  const [searchCard, setSearchCard] = useState("");

  const handleChange = (event) => {
    setCardName(event.target.value);
  };
  const handleKeyDown = (event) => {
    if (event.key == "Enter") {
      setSearchCard(cardName);
      fetch(`https://db.ygoprodeck.com/api/v7/cardinfo.php?name=${searchCard}`)
        .then((response) => response.json())
        .then((json) => console.log(json));
    }
  };

  return (
    <>
      <Box className={styles.container}>
        <Input
          size="lg"
          bg="#e8f1f2"
          placeholder="Search for a card"
          id="cardName"
          name="cardName"
          value={cardName}
          onChange={handleChange}
          onKeyDown={handleKeyDown}
          className={styles.input}
        ></Input>
        <ul className={styles.list}></ul>
      </Box>
    </>
  );
}

问题原因

React的setState是异步更新状态的。在handleKeyDown函数里,调用setSearchCard(cardName)后立刻使用searchCard发起请求,此时searchCard还没完成更新,依然是旧值,导致请求用的是上一次的搜索关键词,所以需要第二次回车才能拿到正确结果。

解决方案

方案一:直接使用当前输入值发起请求(简洁版)

不需要额外维护searchCard状态,直接用cardName的值发起请求,避免异步状态更新的问题:

import { Box, Input } from "@chakra-ui/react";
import styles from "../styles/search.module.css";
import React, { useState } from "react";

export default function Search() {
  const [cardName, setCardName] = useState("");

  const handleChange = (event) => {
    setCardName(event.target.value);
  };
  const handleKeyDown = (event) => {
    if (event.key === "Enter") {
      // 直接使用当前输入的cardName发起请求
      fetch(`https://db.ygoprodeck.com/api/v7/cardinfo.php?name=${cardName}`)
        .then((response) => response.json())
        .then((json) => console.log(json));
    }
  };

  return (
    <>
      <Box className={styles.container}>
        <Input
          size="lg"
          bg="#e8f1f2"
          placeholder="Search for a card"
          id="cardName"
          name="cardName"
          value={cardName}
          onChange={handleChange}
          onKeyDown={handleKeyDown}
          className={styles.input}
        ></Input>
        <ul className={styles.list}></ul>
      </Box>
    </>
  );
}

方案二:用useEffect监听状态变化(适合需保留搜索词的场景)

如果需要把搜索关键词存下来做其他用途(比如显示当前搜索词、记录历史),可以用useEffect监听searchCard的变化,等状态更新完成后再发起请求:

import { Box, Input } from "@chakra-ui/react";
import styles from "../styles/search.module.css";
import React, { useState, useEffect } from "react";

export default function Search() {
  const [cardName, setCardName] = useState("");
  const [searchCard, setSearchCard] = useState("");

  const handleChange = (event) => {
    setCardName(event.target.value);
  };
  const handleKeyDown = (event) => {
    if (event.key === "Enter") {
      setSearchCard(cardName);
    }
  };

  // 当searchCard状态更新时,发起请求
  useEffect(() => {
    if (searchCard) {
      fetch(`https://db.ygoprodeck.com/api/v7/cardinfo.php?name=${searchCard}`)
        .then((response) => response.json())
        .then((json) => console.log(json));
    }
  }, [searchCard]);

  return (
    <>
      <Box className={styles.container}>
        <Input
          size="lg"
          bg="#e8f1f2"
          placeholder="Search for a card"
          id="cardName"
          name="cardName"
          value={cardName}
          onChange={handleChange}
          onKeyDown={handleKeyDown}
          className={styles.input}
        ></Input>
        <ul className={styles.list}></ul>
      </Box>
    </>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 22:57:47