如何在React状态更新后再执行API查询?
解决状态更新前触发API查询的问题
核心问题分析
- 组件顶层直接调用查询钩子,初始状态下
dogInfo.breed为空,触发无效API请求 - 查询参数传递方式错误:API切片定义接收包含
breed和subBreed的对象,你却分开传递两个参数 - 使用
useRef管理输入值不符合React状态管理逻辑,容易引发状态不同步问题
解决方案步骤
- 用
useState替代useRef管理输入:直接将输入值存入状态,避免手动操作ref的同步问题 - 给查询钩子添加
skip条件:当breed为空时跳过查询,仅在状态更新且breed有效时触发API请求 - 修正查询参数传递方式:按照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
相关产品推荐
相关产品推荐

