0

I'm trying to query data from an api by passing it a breed and a sub-breed as arguments. I'm storing these values as state and updating them on button click.

Does anyone know how to query the data only AFTER the state has been updated? Because otherwise the arguments would be undefined and I'd get an error.

I tried putting the hook inside the handleClick function but I got an error telling me it was an invalid hook call.

Any ideas?

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

const SpecificBreed = () => {
  const inputRef = useRef("");
  const inputRef2 = useRef("");
  const [dogInfo, setDogInfo] = useState({
    subBreed: "",
    breed: "",
  });
  const { data, isSuccess } = useGetImageByBreedQuery(
    dogInfo.breed,
    dogInfo.subBreed
  );

  let images = [];

  function handleClick() {
    setDogInfo({
      subBreed: inputRef2.current,
      breed: inputRef.current.replace(/\s/g, ""),
    });
  }

  function handleChange(event) {
    inputRef.current = event.target.value;
  }

  function handleChange2(event) {
    inputRef2.current = event.target.value;
    console.log(inputRef2);
  }

  if (isSuccess) {
    let arrayCopy = {
      ...data.message,
    };
    Object.values(arrayCopy).map((image) => {
      if (image) {
        images.push(
          <ImageListItem
            key={
              image.includes("(")
                ? image.substring(0, image.length - 5) +
                  image.substring(image.length - 4, image.length)
                : image
            }
            cols={Math.floor(Math.random() * 2) + 2}
            rows={Math.floor(Math.random() * 2) + 2}
            sx={{
              "&.MuiImageListItem-root": {
                border: `2px solid black`,
              },
            }}
          >
            <img
              src={image.includes("xeshaBelka") ? "" : image}
              alt="dog"
              loading="lazy"
            />
          </ImageListItem>
        );
      }
    });
  }
  return (
    <Box
      width="100%"
      display="flex"
      justifyContent="center"
      marginTop="350px"
      flexDirection="column"
      gap="5rem"
      alignItems="center"
      sx={{}}
    >
      <Box
        width="50%"
        display="flex"
        justifyContent="center"
        alignItems="center"
        flexDirection="column"
        gap="20px"
      >
        <TextField
          variant="outlined"
          label="Enter a breed..."
          sx={{ width: "100%" }}
          inputRef={inputRef}
          onChange={(event) => handleChange(event)}
        />
        <TextField
          variant="outlined"
          label="Enter a sub-breed..."
          sx={{ width: "100%" }}
          inputRef={inputRef2}
          onChange={(event) => handleChange2(event)}
        />
        <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;

The API's running fine, I tried it with hard-coded values but here it is:

import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";

export const apiSlice = createApi({
  reducerPath: "api",
  baseQuery: fetchBaseQuery({
    baseUrl: "https://dog.ceo/api/",
  }),
  tagTypes: ["Dogs"],
  endpoints: (builder) => ({
    getAllDogs: builder.query({
      query: () => `breeds/list/all`,
      //   providesTags: (result) =>
      //     result ? result.map(({ id }) => ({ type: "Dogs", id })) : [],
    }),
    getRandomImage: builder.query({
      query: (number) => `breeds/image/random/${number}`,
    }),
    getImageByBreed: builder.query({
      query: ({ breed, subBreed }) =>
        `breed/${breed}/${subBreed}/images/random`,
    }),
  }),
});

export const {
  useGetAllDogsQuery,
  useGetRandomImageQuery,
  useGetImageByBreedQuery,
} = apiSlice;
ether
  • 91
  • 5

1 Answers1

0

You can use useEffect if you want to provide a side effect if there is a change in state.

example:

const [state, setState] = useState(null)

useEffect(() => {
  if(!state) return
  // this is the place for the function that will be given a side effect
  getData(); //example
},[state])

if the state changes, then the function getData() inside useEffect will change. if state is null, getData() will not be executed.

Ardhi Cho
  • 41
  • 1
  • 5