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

如何在React状态更新后再执行API查询?

解决状态更新前触发API查询的问题

核心问题分析

  • 组件顶层直接调用查询钩子,初始状态下dogInfo.breed为空,触发无效API请求
  • 查询参数传递方式错误:API切片定义接收包含breed和subBreed的对象,你却分开传递两个参数
  • 使用useRef管理输入值不符合React状态管理逻辑,容易引发状态不同步问题

解决方案步骤

  1. 用useState替代useRef管理输入:直接将输入值存入状态,避免手动操作ref的同步问题
  2. 给查询钩子添加skip条件:当breed为空时跳过查询,仅在状态更新且breed有效时触发API请求
  3. 修正查询参数传递方式:按照API切片定义,传递包含breed和subBreed的对象作为参数

修改后的组件代码

import React, { useState } from "react";
import { useGetImageByBreedQuery } from "../features/api/apiSlice";
import { Button, ImageList, TextField, Box, ImageListItem } from "@mui/material";

const SpecificBreed = () => {
  // 用useState管理输入值,替代ref
  const [breedInput, setBreedInput] = useState("");
  const [subBreedInput, setSubBreedInput] = useState("");
  const [dogInfo, setDogInfo] = useState({
    subBreed: "",
    breed: "",
  });

  // 传递正确的对象参数,添加skip条件:breed为空时不查询
  const { data, isSuccess } = useGetImageByBreedQuery(dogInfo, {
    skip: !dogInfo.breed
  });

  const handleClick = () => {
    // 点击按钮时更新查询用的状态
    setDogInfo({
      subBreed: subBreedInput.trim(),
      breed: breedInput.trim().replace(/\s/g, ""),
    });
  };

  // 渲染图片列表
  const images = isSuccess 
    ? Object.values(data.message).map(image => {
        // 跳过无效图片
        if (!image || image.includes("xeshaBelka")) return null;
        
        // 生成唯一key
        const key = image.includes("(") 
          ? `${image.slice(0, -5)}${image.slice(-4)}` 
          : image;

        return (
          <ImageListItem
            key={key}
            cols={Math.floor(Math.random() * 2) + 2}
            rows={Math.floor(Math.random() * 2) + 2}
            sx={{
              "&.MuiImageListItem-root": {
                border: `2px solid black`,
              },
            }}
          >
            <img src={image} alt="dog" loading="lazy" />
          </ImageListItem>
        );
      })
    : [];

  return (
    <Box
      width="100%"
      display="flex"
      justifyContent="center"
      marginTop="350px"
      flexDirection="column"
      gap="5rem"
      alignItems="center"
    >
      <Box
        width="50%"
        display="flex"
        justifyContent="center"
        alignItems="center"
        flexDirection="column"
        gap="20px"
      >
        <TextField
          variant="outlined"
          label="Enter a breed..."
          sx={{ width: "100%" }}
          value={breedInput}
          onChange={(e) => setBreedInput(e.target.value)}
        />
        <TextField
          variant="outlined"
          label="Enter a sub-breed..."
          sx={{ width: "100%" }}
          value={subBreedInput}
          onChange={(e) => setSubBreedInput(e.target.value)}
        />
        <Button
          variant="contained"
          sx={{ width: "100%" }}
          onClick={handleClick}
        >
          Find Pictures
        </Button>
      </Box>
      <ImageList variant="masonry" cols={4} gap={8} sx={{ p: "1rem" }}>
        {images}
      </ImageList>
    </Box>
  );
};

export default SpecificBreed;

补充优化(可选)

如果需要处理无品种的情况,可以修改API切片中的路径逻辑,避免生成带空值的无效路径:

getImageByBreed: builder.query({
  query: ({ breed, subBreed }) => {
    // 无品种时拼接正确路径
    const path = subBreed ? `breed/${breed}/${subBreed}/images/random` : `breed/${breed}/images/random`;
    return path;
  },
}),

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 05:47:52