Home > Software design >  Why to use square brackets [ ] when using custom hook
Why to use square brackets [ ] when using custom hook

Time:11-09

I understand destructuring that it unpacks values from array into variables and using square brackets in useState means it is returning two values in that array, first one is value and second one is function that is used to change that value, But I see [] when using custom hook, and It does not make any sense to me , Can anyone please explain me why variable [breeds] has square brackets around it. it is declared under useState.

    const ANIMALS = ["bird", "cat", "dog", "rabbit", "reptile"];



export const SearchParams = () => {
    const [location, setLocation] = useState("");
    const [animal, setAnimal] = useState('');
    const [breed, setBreed] = useState('')
    const [pets, setPets] = useState([]);
    const [breeds] = useBreedList(animal); 
  
  useEffect(() => {
    requestPets();
},[animal])

  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(); 
    console.info('json is ' JSON.stringify(json))
    setPets(json.pets);
    console.warn("pets are "   JSON.stringify(pets));
  }
    return (
      <div className="search-params">
        

        <form>
          <label htmlFor="location">
            Location
            <input
              id="location"
              value={location}
              placeholder="Location"
              onChange={(e) => setLocation(e.target.value)}
            />
          </label>
          <label htmlFor="animal">
            Animal
            <select
              id="animal"
              value={animal}
              onChange={(e) => {
                setAnimal(e.target.value);
                setBreed("");
              }}
              onBlur={(e) => {
                setAnimal(e.target.value);
                setBreed("");
              }}
            >
              <option />
              {ANIMALS.map((animal) => (
                <option key={animal}>{animal}</option>
              ))}
            </select>
          </label>
          <label htmlFor="breed">
            Breed
            <select
              id="breed"
              value={breed}
              onChange={(e) => setBreed(e.target.value)}
              disabled={breeds.length === 0}
            >
              <option />
              {breeds.map((breed) => (
                <option key={breed}>{breed}</option>
              ))}
            </select>
          </label>
          <button>Submit</button>
        </form>
        {pets.map((pet) => (
          <Pet
            name={pet.name}
            animal={pet.animal}
            breed={pet.breed}
            key={pet.id}
          />
        ))}
      </div>
    );
}

This is custom hook

    const localCache = {};

export const useBreedList = (animal) => {
    const [breedList, setBreedList] = useState([]);
    const [status, setStatus] = useState("unloaded"); 

    useEffect(() => {
      
        if (!animal) {
            setBreedList([])

        } else if (localCache[animal]) {
            setBreedList(localCache[animal])
            
        } else {
            requestBreedList();
        }

        async function requestBreedList() {
           
            setBreedList([]);
            setStatus("loading");
            const res = await fetch(
                `https://pets-v2.dev-apis.com/breeds?animal=${animal}`
            )
            const json = await res.json();
            
            localCache[animal] = json.breeds || [] 
            
            setBreedList(localCache[animal]);
            setStatus("loaded");
        }
    }, [animal]);

    return [breedList, status];
}

CodePudding user response:

Can anyone please explain me why variable [breeds] has square brackets around it. it is declared under useState.

Because it's destructuring the result of calling useBreedList, which (like useState) returns two pieces of information, wrapped up in a tuple (a fixed-length array):

export const useBreedList = (animal) => {
    // ...
    return [breedList, status]; // <=================================
};

Since they're returning two pieces of information, the people writing useBreedList had the same choice that the people writing useState did:

  1. Return a tuple (fixed-length array) people can destructure into variables they control the names of

  2. Return an object with (say) breedlist and status properties

It's easier to control your own variable names when using the hook when the hook uses a tuple (#1) rather than an object (#2) — and indeed, the code you've quoted is using breeds rather than breedList. If the hook did this:

return { breedList, status };

...then the quoted code would have had to do this to use the name breeds instead:

const { breedList: breeds } = useBreedList(animal);

That said, this hook is really specific, I wouldn't have been surprised to find it written using a (non-array) object instead, and for code using it to consistently use const { breedList, status } = useBreedList(animal); instead.

  • Related