Заполнение пустых блоков для каждого календарного месяца JS

#javascript #reactjs

#javascript #reactjs

Вопрос:

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

Код, который я в настоящее время использую для извлечения каждого календарного месяца и их отображения, выглядит следующим образом:

 import React, { useEffect, useState, useCallback } from "react";
import "./styles.css";

export default function App() {
  const [visibleMonth, setVisibleMonth] = useState(new Date().getMonth());
  const [calData, setCalData] = useState(null);
  const [dates, setDates] = useState(null);

  const getDaysArray = async (s, e) => {
    let a = [];
    for (let d = new Date(s); d <= e; d.setDate(d.getDate()   1)) {
      a.push(new Date(d).toString());
    }
    return a;
  };

  const currentMonth = useCallback(async () => {
    let d = new Date();
    d.setMonth(visibleMonth);
    let firstDay = new Date(d.getFullYear(), d.getMonth(), 1);
    let lastDay = new Date(firstDay.getFullYear(), firstDay.getMonth()   1, 0);
    let calendarMonth = d.toLocaleString("en-us", {
      month: "long",
      year: "numeric"
    });
    setCalData(calendarMonth);
    const dates = await getDaysArray(firstDay, lastDay);

    setDates(dates);
  }, [visibleMonth]);

  useEffect(() => {
    currentMonth();
  }, [currentMonth]);

  const prevMonth = async () => {
    let d = new Date();
    d.setMonth(visibleMonth - 1);
    setVisibleMonth((state) => visibleMonth - 1);
    let firstDay = new Date(d.getFullYear(), d.getMonth(), 1);
    let lastDay = new Date(firstDay.getFullYear(), firstDay.getMonth()   1, 0);
    let calendarMonth = d.toLocaleString("en-us", {
      month: "long",
      year: "numeric"
    });
    setCalData(calendarMonth);
    const dates = await getDaysArray(firstDay, lastDay);
    setDates(dates);
  };

  const nextMonth = async () => {
    let d = new Date();
    d.setMonth(visibleMonth   1);
    setVisibleMonth((state) => visibleMonth   1);

    let firstDay = new Date(d.getFullYear(), d.getMonth(), 1);
    let lastDay = new Date(firstDay.getFullYear(), firstDay.getMonth()   1, 0);
    let calendarMonth = d.toLocaleString("en-us", {
      month: "long",
      year: "numeric"
    });
    setCalData(calendarMonth);
    const dates = await getDaysArray(firstDay, lastDay);
    setDates(dates);
  };

  return (
    <div className="App">
      <h1>{calData}</h1>
      <button onClick={prevMonth}>Prev Month</button>
      <button onClick={nextMonth}>Next Month</button>
      {dates amp;amp;
        dates.map((item, i) => {
          return <div key={i}>{item}</div>;
        })}
    </div>
  );
}
 

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

Прилагается ручка с кодом для отладки! https://codesandbox.io/s/heuristic-visvesvaraya-r9lcw?file=/src/App.js

Комментарии:

1. Еще раз здравствуйте, Роберт — возможно, вы немного задумались об этом. У вас уже есть то, что вам нужно, предполагая, что вы собираетесь разместить это в сетке. Предполагая, что первый элемент сетки в строке, скажем, сетка 0, является воскресеньем, тогда использование .getDay() вернет размещение сетки для каждого дня. Это будет работать, потому .getDay() что возвращает нулевое индексированное значение для каждого дня с — как вы уже догадались; Воскресенье равно 0. Итак, вторник, 1 декабря, будет автоматически и динамически отображаться в третьем элементе сетки (или сетке 2), потому .getDay() что вернет 2. Надеюсь, это поможет.

2. так я бы вызвал getDay() в цикле for?

3. Трудно отвечать на общие вопросы, не понимая вашего дизайна. Например, я понятия не имею, почему вы храните даты в виде строк, зная, что вы хотите делать что-то, основываясь на том, что они являются точными датами (а не строками). Поэтому я не могу ответить на этот вопрос.

4. Я внес изменения в свой вопрос и песочницу, чтобы показать мой текущий стиль и почему я пытаюсь заполнить пустые дни

Ответ №1:

Основываясь на ваших последних комментариях и обновлениях, я рекомендую внести следующие изменения в getDaysArray() метод:

  1. Создайте d дату вне цикла, чтобы использовать getDay() (день недели #)
  2. a[] Заполните пустыми строками с номером дня недели # в цикле for
  3. Наконец, заполните строки даты в оставшуюся часть a[] массива.

Это должно сделать это:

 const getDaysArray = async (s, e) => {
    let a = [];
    let d = new Date(s);
    let emptyCount = d.getDay();
    for(let i = 0; i < emptyCount; i  ) {
      a.push('');
    }
    for (d; d <= e; d.setDate(d.getDate()   1)) {
      a.push(new Date(d).toString());
    }
    return a;
  };
 

Комментарии:

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

2. Теперь, когда я увидел ваши намерения с ними, они в порядке. Я на самом деле выступаю за форматирование даты с использованием строк — до последних версий API Date это был самый простой / быстрый способ выполнить это (форматирование даты). Как вы делаете. Это выглядит хорошо.

3. спасибо, Рэнди, ты мне очень помог! и я также ценю ваше объяснение вашей логики

4. Добро пожаловать. До следующего раза 🙂