Добавляйте состояние isLoading при загрузке данных

Допустим, вы делаете react-компонент, где загружаются и выводятся данные. Максимально упростил для примера:

Если пользователи есть, то отображаем список. Если нет, то пишем, что пользователи не найдены.Если пользователи есть, то отображаем список. Если нет, то пишем, что пользователи не найдены.

С продуктовой точки зрения здесь баг: пока грузится список, человек видит текст, что пользователей нет. Человек говорит про себя «ну, ок» и уходит заниматься своими делами.

В настоящем проекте это может помешать работе. Например, если вы делаете таблицу для менеджера со списком клиентов, которым нужно написать. Если вы сходу напишете, что таблица пустая, хотя на самом деле вы просто загружаете список, то менеджер справедливо решит, что работы на сегодня нет и уйдет со страницы.

Пользователи на самом деле есть — они просто грузятся.Пользователи на самом деле есть — они просто грузятся.

Чтобы решить это баг, надо добавить еще одно состояние isLoading. Через него вы показываете, что данные загружаются и не путаете пользователя нерелевантным текстом.

Больше не вводим пользователя в заблуждение.Больше не вводим пользователя в заблуждение.

Обратите внимание на конструкцию finally. Некоторые сбрасывают загрузчик только в then, но это неправильно, ведь если при запросе случилась ошибка, то загрузчик тоже надо сбросить.

Но если случилась ошибка при загрузке, а мы пишем, что пользователей нет, это ведь тоже вводит пользователя в заблуждение, не так ли?

Кейс с ошибками тоже лучше покрыть отдельным состоянием isError. К слову, в библиотеках, типа react-query заботятся о таких кейсах, выдавая флаги isLoading и isError, данные в data и ошибку в error.

Пример из документации react-queryПример из документации react-query

Состояние isLoading — полезный паттерн, когда надо показать загрузку данных. Без такого состояния пользователь войдет в заблуждение и скорее всего не дождется загрузки, особенно при медленном интернете.

Итоговый код нашего упрощенного примера с загрузкой пользователей:

export const UsersList = () => {
  const [users, setUsers] = useState<User[]>([]);
  const [isLoading, setLoader] = useState(false);
	const [error, setError] = useState<Error | null>(null);

  useEffect(() => {
    setLoader(true);
    setError(null);

    fetchUsers()
      .then(setUsers)
      .catch((error: Error) => {
        setError(error);
      })
      .finally(() => setLoader(false));
  }, []);

  if (isLoading) {
    return <p>Загрузка пользователей…</p>;
  }

  if (error !== null) {
    return <p>Случилась ошибка, попробуйте позже. {error.message}</p>;
  }

  return (
    <div>
      {users.length
        ? users.map(({ name }) => <p>{name}</p>)
        : "Пользователи не найдены"}
    </div>
  );
}