We have enough to start making some requests now. We want the app to request an initial set of pets on initial load of the page. So let's make that happen using a special hook called useEffect. useEffect allows you to say "do a render of this component first so the user can see something then as soon as the render is done, then do something (the something here being an effect.) In our case, we want the user to see our UI first then we want to make a request to the API so we can that initial list of pets.

Add this to SearchParams.js

// change import at top
import { useEffect, useState } from "react";
import Pet from "./Pet";

// add to the other useStates inside component at top
const [pets, setPets] = useState([]);

// add inside component, beneath all the `useState` setup
useEffect(() => {
  requestPets();
}, []); // eslint-disable-line react-hooks/exhaustive-deps

async function requestPets() {
  const res = await fetch(
    `http://pets-v2.dev-apis.com/pets?animal=${animal}&location=${location}&breed=${breed}`
  );
  const json = await res.json();

  setPets(json.pets);
}

// in jsx, under form, inside the larger div
{
  pets.map((pet) => (
    <Pet name={pet.name} animal={pet.animal} breed={pet.breed} key={pet.id} />
  ));
}

🚨 If you're seeing an error about regeneratorRuntime, please go back to the Browserslist lesson and make sure you followed that. If you have and it's still broke, please delete your node_modules, .cache, and dist directories, run npm install again, and try running npm run dev again.

  • We're taking advantage of closures here that if we define the requestPets function inside of the render that it will have access to that scope and can use all the hooks there.
  • We could have actually put requestPets inside of the effect but we're going to use it again here in a sec with the submit button.
  • the [] at the end of the useEffect is where you declare your data dependencies. React wants to know when to run that effect again. You don't give it data dependencies, it assumes any time any hook changes that you should run the effect again. This is bad because that would mean any time setPets gets called it'd re-run render and all the hooks again. See a problem there? It'd run infinitely since requestPets calls setPets.
  • You can instead provide which hooks to watch for changes for. In our case, we actually only want it to run once, on creation of the component, and then to not run that effect again. (we'll do searching later via clicking the submit button) You can accomplish this only-run-on-creation by providing an empty array.
  • The // eslint-disable-line react-hooks/exhaustive-deps tells eslint to shut up about this one run on this one line. Why? Because eslint tries to help you with you the data dependencies rule by watching for anything that could change. In this case, in theory the function could change but we know it's not important. You'll end up silencing this rule a fair bit.
  • At the end, we gather take the pets we got back from the API and create Pet components out of each of them.

🏁 Click here to see the state of the project up until now: 05-useeffect