У меня очень простой функциональный компонент, который получает дату из localStorage и отображает ее. У меня есть две кнопки для добавления или удаления недель с даты, и я ожидаю, что будет показана новая дата. Однако компонент не отображается.

import React, { useState } from "react";
import { monthList } from "../common/lists";

const Navbar = () => {
  const [focusDate, setFocusDate] = useState(
    Number(localStorage.getItem("focusDate"))
  );

  const [month] = useState(new Date(focusDate).getMonth());
  const [year] = useState(new Date(focusDate).getFullYear());

  const onLeftClick = () => {
    setFocusDate(focusDate - 504000000); //one week
    localStorage.setItem("focusDate", focusDate);
  };

  const onRightClick = () => {
    setFocusDate(focusDate + 504000000);
    localStorage.setItem("focusDate", focusDate);
  };

  return (
    <div className="navbar-container">
      <div className="calendar-navigation-container">
        <div className="navbar-menu-item">
          <i onClick={onLeftClick} className="fas fa-chevron-left"></i>
        </div>
        <div onClick={onRightClick} className="navbar-menu-item">
          <i className="fas fa-chevron-right"></i>
        </div>
        <div className="calendar-year">{`${monthList[month]} ${year}`}</div>
      </div>
    </div>
  );
};

Ожидаемое поведение этого компонента заключается в том, что он получает метку времени, а затем показывает месяц и год этой метки времени. При загрузке он правильно показывает январь 2021 года, однако он не отображает компонент, когда я несколько раз нажимаю onLeftClick, хотя я ожидал, что он покажет декабрь 2021 года. Расчеты верны, я думаю, что здесь отсутствует концепция рендеринг функциональных компонентов. С компонентами Class это было бы намного проще, но я хочу изучить и функциональные. Что мне здесь не хватает?

0
Ruham 17 Янв 2021 в 13:14

2 ответа

Лучший ответ

Кажется, вы ожидаете, что setFocusDate будет синхронным, что не так. Поэтому, если вы вызываете setFocusDate и сразу после этого (следующая строка) обновляете локальное хранилище с помощью focusDate, вы не можете ожидать, что локальное хранилище будет содержать новое значение focusDate. Вы можете, например, прочитать это здесь.

В вашем примере я подозреваю, что обновление локального хранилища выполняется с предыдущим значением состояния, потому что setFocusDate запланирован, но еще не выполнен React.

Если вы хотите обновить локальное хранилище вместе с состоянием (состояние синхронизации с локальным хранилищем), вам необходимо использовать useEffect с focusDate в массиве зависимостей (второй аргумент для useEffect, поэтому при изменении focusDate запускается useEffect). :

useEffect(() => {
  // this function will be called after focusDate changed
  // update local storage here
}, [focusDate]);

Кроме того, вы можете использовать специальный перехватчик для синхронизации локального хранилища с состоянием компонента, подобным этому: https: // usehooks. ru / useLocalStorage /

1
Florian Motteau 17 Янв 2021 в 10:27

Вам не нужно делать переменные месяца и года частью состояния, потому что их значение учитывается только один раз. Достаточно просто утверждения

const month = new Date(focusDate).getMonth();
const year = ew Date(focusDate).getFullYear();
1
Dmitry Reutov 17 Янв 2021 в 10:22