Let's go do SearchParams.tsx
// import Animal type
import { Animal } from "./APIResponsesTypes";
const ANIMALS: Animal[] = ["bird", "cat", "dog", "rabbit", "reptile"];
// replace useState calls
const [animal, updateAnimal] = useState("" as Animal);
<form
onSubmit={(e) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
const obj = {
animal: formData.get("animal")?.toString() ?? "",
breed: formData.get("breed")?.toString() ?? "",
location: formData.get("location")?.toString() ?? "",
};
setRequestParams(obj);
}}
>
[…]
</form>
// add as to select for animal
<select
id="animal"
name="animal"
onChange={(e) => {
setAnimal(e.target.value as Animal);
}}
onBlur={(e) => {
setAnimal(e.target.value as Animal);
}}
>
[…]
</select>
- We had to switch from
e.target
toe.currentTarget
because I guess while target works it's not technically guaranteed to be on a submit event even though it always is 🤷♂️ - Working with the DOM with TypeScript can get annoying because there's a lot of legacy pseudo types that we never had to care about. Technically
formData.get
gives us back aFormDataEntryValue
type and not a string but when you use it like we were it implicitly calledtoString
. Now we have to do it explictly. - We need to type values as they come out of the DOM. There's no way for TypeScript to understand what goes into the DOM and what comes back out so we have to be explicit as it goes in and out.