youkichi
youkichi

Reputation: 23

How to specify the type

I am learning typescript.

I used axios and stored the api return value in useEffect and displayed it on the screen, but I get an error saying that there is no name in the interface todoList. What is the cause?

thank you.

import React, {useEffect, useState} from 'react';
import axios from 'axios';

interface todoList {
    name: string
    age: number
}

function App() {

    const defaultProps: todoList[] = [];
    const [todoList, setTodoList]: [todoList[], (todoList: todoList[]) => void] = useState(defaultProps);

  useEffect(() => {
        async function getTodo() {
            const response = await axios.get('http://localhost/laravel/public/api/todo');
        setTodoList(response.data);
        }
       getTodo();
  }, []);

  return (
      <div className="App">
          {todoList.name} // Error here.
    </div>
  );
}

export default App;

Upvotes: 1

Views: 68

Answers (2)

Ruchi Tiwari
Ruchi Tiwari

Reputation: 261

Point1: This is because UI gets rendered before useEffect and hence the moment UI gets rendered it looks for todolist.name where todolist is empty and fetching name throws error. If specific name of any items is to be displayed check the array length and name is not null before mapping to UI

Point2: If all the names is to placed in UI then map the array as below

 import React, {useEffect, useState} from 'react';
 import axios from 'axios';

  function App() { 
  const [todoList, setTodoList] = useState([]);
  useEffect(() => {
  async function getTodo() {
  const response = await axios.get('http://localhost/laravel/public/api/todo');
  setTodoList(response.data);
   }
 getTodo();
 }, []);

 return (
  <div>
    {todoList.map((todo) =>
    <p> {todo.name} </p>
    )}
  </div>
 );
  }

 export default App;

Upvotes: 2

Kelvin Schoofs
Kelvin Schoofs

Reputation: 8718

Your todoList variable is an array of todoLists, e.g. todoList[]. You're trying to read .name of an array, which isn't defined.

You probably want to display a list of items:

return <div className="App">
    {todoList.map(todo => <div key={todo.name}>
        {todo.name}
    </div>)}
</div>;

Your typing otherwise seems fine. One suggestion for readability that I have is simplifying your useState statement:

const [todoList, setTodoList] = useState<todoList>(defaultProps);

With how React declared the type of useState, you can use useState<T> and it'll automatically know that it's returning a [T, (value: T) => void].

Another small note: Usually interfaces/types are PascalCase, e.g. TodoList, to make sure it doesn't clash with variables and function parameters which usually have camelCase, e.g. your todoList variable.

Upvotes: 1

Related Questions