DEV Community

Serhii Zadorozhnyi
Serhii Zadorozhnyi

Posted on

How to Fetch API Data with UseEffect

In this example we going to fetch todos via useEffect and fetch for TodoList component.

TodoList.tsx

import { useEffect, useState } from 'react';
import { Todo } from '../types';

const TodoList = () => {
  // Setting states
  const [isLoaded, setIsLoaded] = useState(false);
  const [errorMessage, setErrorMessage] = useState('');
  const [todos, setTodos] = useState<Todo[]>([]);

  useEffect(() => {
    // For axios need to use cancelToken function provided by axios
    const controller = new AbortController();
    // Aborts a DOM request before it has completed. For example
    // switching pages or changing component
    const signal = controller.signal;
    // signal should be provided to fetch options
    fetch('https://jsonplaceholder.typicode.com/todos', { signal })
      .then((response) => response.json())
      .then((body) => {
        setErrorMessage('');
        setTodos([...body]);
        setIsLoaded(true);
      })
      .catch((error) => {
        if (error.name !== 'AbortError') {
          setErrorMessage('Unable to load todos');
          console.error(error);
        }
        setIsLoaded(true);
      });

    return () => controller.abort();
  }, []);

  // Getting 10 todos
  const slicedTodos = todos.slice(0, 10).map((todo) => {
    return (
      <div key={todo.id} className="flex justify-between">
        <div>{todo.title}</div>
        <div>{todo.completed ? 'Completed' : 'Not Completed'}</div>
      </div>
    );
  });

  return (
    <div className="flex flex-col">
      // Show error message if not empty
      {errorMessage !== '' && <div>{errorMessage}</div>}
      // Show todos if they loaded and no error
      {isLoaded && errorMessage === "" ? slicedTodos : <div>Loading...</div>}
    </div>
  );
};

export default TodoList;

Enter fullscreen mode Exit fullscreen mode

App.tsx

import './App.css';
import TodoList from './components/TodoList';

function App() {
  return (
    <div className="App">
      <TodoList />
    </div>
  );
}

export default App;

Enter fullscreen mode Exit fullscreen mode

Code example: https://github.com/DarthRevanXX/react-fetch-example

Top comments (0)