Я работаю над приложением todo с React, и все становится яснее, но мне трудно понять «жизненный цикл». В VueJS я знаю ловушку ComponentDidMount(), которая поможет мне решить эту проблему, если я предполагаю, но в React я не могу этого найти.

У меня есть набор задач вроде этого: const todos = [{description: "walk dog", done: false}]

Это начальное состояние моего приложения:

const [alltodos, handleTodos] = useState([]);

При загрузке я использую эту ловушку useEffect для получения данных из localStorage.

  useEffect(() => {
    const items = localStorage.getItem("todos");
    const parsed = JSON.parse(items);
    handleTodos(parsed);
  }, []);

Я считаю свои задачи с помощью этой функции:

  const countTodos = () => {
    const donetodos = alltodos.filter((item) => {
      return !item.done;
    });

    countOpen(donetodos.length);
  };

Я обновляю счетчик, если изменяется зависимость:

  useEffect(() => {
    countTodos();
    localStorage.setItem("todos", JSON.stringify(alltodos));
  }, [alltodos]);

Итак, что происходит, так это то, что счетчик начинается с 0 и затем «мерцает» в течение миллисекунды, прежде чем он показывает количество задач, которые я получаю из localstorage.

Есть ли способ предотвратить такое поведение? Насколько я знаю, компонент отображается ПЕРВЫМ, а затем срабатывает ловушка useEffect. Как я визуализирую свой компонент ПОСЛЕ того, как данные извлекаются из локального хранилища?

0
Data Mastery 17 Сен 2021 в 20:51

3 ответа

Лучший ответ

Лучше всего это сделать с помощью ленивого начального состояния . Кроме того, очистка переменных и использование стандартизированной [переменной, setVariable] избавит вас от головной боли при отладке в будущем.

const [alltodos, setAlltodos] = useState(() => {
    const items = localStorage.getItem("todos");
    const parsed = JSON.parse(items);
    return parsed || "";
});
1
Colin 17 Сен 2021 в 18:23

Инициализируйте состояние allTodos с помощью null. Пока это состояние равно null, отображать уведомление или просто возвращать null, чтобы ничего не отображать.

Вы можете рассчитать количество открытых задач непосредственно из текущего состояния alltodos, без необходимости useEffect.

const [alltodos, handleTodos] = useState(null);

useEffect(() => {
  const items = localStorage.getItem("todos");
  const parsed = items ? JSON.parse(items) : [];
  handleTodos(parsed);
}, []);

useEffect(() => {
  localStorage.setItem("todos", JSON.stringify(alltodos));
}, [alltodos]);

if(alltodos === null) return 'Loading todos list';

// this is derived from state, so you don't have to create a state for it
const openTodosCount = alltodos.reduce((acc, o) => acc + !o.done, 0);
1
Ori Drori 17 Сен 2021 в 18:06

Самый быстрый способ - добавить новое состояние, которое будет отвечать за загрузку. Например

const [isLoading, setIsLoading] = useState(true);

Сначала установите значение true, а затем, после того, как вы выполните все свои вычисления, измените его на false.

Затем вы можете зависеть от этого состояния и отображать div с текстом "Loading" или чем-то еще, но когда isLoading перейдет к false, он покажет элементы компонентов.

0
Sowam 17 Сен 2021 в 17:58