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 underuseState
.
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:
Return a tuple (fixed-length array) people can destructure into variables they control the names of
Return an object with (say)
breedlist
andstatus
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.