2

I am trying to learn using TypeScript in my React projects.

I made a type for the incoming data format (name and url).

type PokedexType = {
    name: string;
    url: string;
}

The data returned from the API is an array of objects (with name and url).

{
"results": [
        {
            "name": "national",
            "url": "https://pokeapi.co/api/v2/pokedex/1/"
        },
        {
            "name": "kanto",
            "url": "https://pokeapi.co/api/v2/pokedex/2/"
        },
        // ...
    ];
}

In my useEffect(), I am storing these objects in a state with setState().

useEffect(() => {
  api.get('/pokedex')
    .then((response) => {
      setPokedex(response.data.results);
    })
    .catch((error) => {
      console.log(error);
    });
});

Because the API returns an array, I am confused about the correct way to setup useState().

// this works
const [pokedex, setPokedex] = useState<Array<PokedexType>>([{ name: "", url: "" }]);
// these also work
const [pokedex, setPokedex] = useState<PokedexType>({ name: "", url: "" });
const [pokedex, setPokedex] = useState<Array<PokedexType>>();
const [pokedex, setPokedex] = useState(); // (with checking)

I understand that specifying type is for type checking, but if the state is overwritten immediately, does this matter?

I am trying to set the states name (i.name) as value for my select, what would be the correct way to do this? Since the state is now an array, how can I set the value to the corresponding property (like this)?

<select value={pokedex.name}>
7
  • I am not entirely sure I understand your question. Are you asking what the point of using types is? Do you have a secondary question about how to change the value of an item in an array using state? Commented Feb 16, 2021 at 20:04
  • shouldn't useState<Array<PokedexType>>([{ name: "", url: "" }]); just be useState<PokedexType[]>([{ name: "", url: "" }]);? Commented Feb 16, 2021 at 20:29
  • @azium they are indeed 2 separate questions, I will try to make that clear Commented Feb 16, 2021 at 21:26
  • @kimbaudi both ways do the same thing (arrname[] and Array<arrname>) Commented Feb 16, 2021 at 21:28
  • 1
    The default linter rule is non-complex types (i.e. a single pre-defined type) should use type[] and a complex types (defined inline / composite types) should use Array<{ name: string; url: string; }> or Array<typeOne & typeTwo>. I do not know if this is a preference only linter rule or has something to do with type resolution speed. Commented Feb 16, 2021 at 21:39

1 Answer 1

1

You can't just say pokedex.name. pokedex is an array, so you have to loop through that array. e.g.

//just a mock, will come from your ajax request
const pokedex = [
    {
        "name": "national",
        "url": "https://pokeapi.co/api/v2/pokedex/1/"
    },
    {
        "name": "kanto",
        "url": "https://pokeapi.co/api/v2/pokedex/2/"
    }
]

const Select = () => ( <select > 
      {pokedex.map(el => < option value = {el.name} >{el.name}</option>)}
</select>)


        // Render it
        ReactDOM.render( <
          Select / > ,
          document.getElementById("react")
        );
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>

Take also a look at interfaces:

interface IPokedex {
    name: string;
    url: string;
}

const [pokedex, setPokedex] = useState<IPokedex[]>([{ name: "", url: "" }]);
Sign up to request clarification or add additional context in comments.

4 Comments

Ok but the parent select tag also has a value prop, what should I bind to this value?
Your pokedex result has no preselected value, so you can keep the select value empty. In that way, it will manage the selection itself. If you wish to preselect it or to control the selection yourself, then you should take a look at the React Controlled Components reactjs.org/docs/forms.html#controlled-components. But what is your final Goal?
Oh ok, I thought setting a value to the select was needed for it to display the right option, I guess I can just leave it out then if my <option>'s have a value.
I adjusted my code snippet, it has no preselected value anymore. Try it out. Did this answer your question?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.