Еженедельное отображение заголовков React JS UseState Расписание

Я работаю над внедрением компонента расписания в реакцию с использованием useState. Я немного запутался с некоторыми функциями и тем, как это работает за кулисами (я все еще учусь, ребята). Когда я нажимаю кнопки управления на предыдущей или следующей неделе, даты меняется случайным образом вместо отображения дат следующей недели текущего месяца или дат предыдущей недели. Другая проблема также заключается в том, что всякий раз, когда я начинаю вводить данные, даты в заголовках также меняются случайным образом.

Мне здесь чего-то не хватает, буду признателен за помощь. Спасибо.

      const TimeSheet = () => {

  const days = ["Mon", "Tue", "Wed", "Thurs", "Fri", "Sat", "Sun"];
  const [startDate, setStartDate] = useState(new Date());
  const [data, setData] = useState([
    { project: 'Project A', hours: [0, 0, 0, 0, 0, 0, 0], total: 0 },
    { project: 'Project B', hours: [0, 0, 0, 0, 0, 0, 0], total: 0 },
  ]);

  const handlePreviousWeek = () => {
    // setStartDate(new Date(startDate.setDate(startDate.getDate() - 7)));

    const prevWeek = new Date(startDate);
    prevWeek.setDate(startDate.getDate() - 7);
    setStartDate(prevWeek);
  };

  const handleNextWeek = () => {
    // setStartDate(new Date(startDate.setDate(startDate.getDate() + 7)));
    const nextWeek = new Date(startDate);
    nextWeek.setDate(startDate.getDate() + 7);
    setStartDate(nextWeek);
  };

  const handleAddRow = () => {
    setData([
      ...data,
      { project: `Project ${data.length + 1}`, hours: [0, 0, 0, 0, 0, 0, 0], total: 0 },
    ]);
  };

  const handleDeleteRow = (index) => {
    const updatedData = [...data];
    updatedData.splice(index, 1);
    setData(updatedData);
  };

  const handleSaveHours = () => {
    console.log('Hours saved:', data);
  };

  // const calculateTotal = (hours) => {
  //   let total = 0;
  //   for (let i = 0; i < hours.length; i++) {
  //     total += parseInt(hours[i]) || 0;
  //   }
  //   return total;
  // };

  const handleHoursChange = (projectIndex, dayIndex, value) => {
    const updatedData = [...data];
    updatedData[projectIndex].hours[dayIndex] = value;
    updatedData[projectIndex].total = updatedData[projectIndex].hours.reduce(
      (acc, cur) => acc + cur,
      0
    );
    setData(updatedData);
  };

  return (
    <div>
      <h1>Project Simple Time Sheet</h1>
      <div>
        <button onClick={handlePreviousWeek}>Previous Week</button>
        {/* <span>{startDate.toLocaleDateString("de-DE")}</span> */}
        <span>{`${startDate.toLocaleDateString('de-DE')} - ${new Date(
              startDate.setDate(startDate.getDate() + 6)
            ).toLocaleDateString('de-DE')}`}</span>
        <button onClick={handleNextWeek}>Next Week</button>
      </div>
      <table>
        <thead>
          <tr>
            <th>Project</th>

            {/* {Array.from({ length: 7 }).map((_, index) => (
              <th key={index}>{new Date(startDate.setDate(startDate.getDate() + 1)).toLocaleDateString("de-DE")}</th>
            ))} */}

          {days.map((day) => (
                  <th key={day}>
                    {day}
                    <br />
                    {new Date(
                      startDate.getFullYear(),
                      startDate.getMonth(),
                      startDate.getDate() + days.indexOf(day)
                    ).toLocaleDateString('de-DE')}
                  </th>
                ))}
            <th>Total</th>
            <th></th>
          </tr>
        </thead>
        <tbody>
          {data.map((item, index) => (
            
            <tr key={index}>
              <td>{item.project}</td>
              {item.hours.map((hour, dayIndex) => (
                <td key={dayIndex}>
                  <input type="number" value={hour} onChange={(e) => handleHoursChange(index, dayIndex,     e.target.value)} />
                </td>
              ))}
              <td>
                {item.total}
            
              
              </td>
              <td><button onClick={() => handleDeleteRow(index)}>Delete</button></td>
            </tr>
          ))}
          <tr>
            <td></td>
            {Array.from({ length: 7 }).map((_, index) => <td key={index}></td>)}
            <td></td>
            <td></td>
          </tr>
        </tbody>
      </table>
      <button onClick={handleAddRow}>Add Row</button>
      <button onClick={handleSaveHours}>Save Hours</button>
      <button onClick={() => console.log('Hours submitted:', data)}>Submit</button>
    </div>
  );
};

export default TimeSheet;

1 ответ

Проблема именно в этой строке:

      <span>{`${startDate.toLocaleDateString('de-DE')} - ${new Date(
      startDate.setDate(startDate.getDate() + 6)
    ).toLocaleDateString('de-DE')}`}</span>

В основном вnew Date(startDate.setDate(startDate.getDate() + 6))Вы звонитеstartDate.setDate(), что означает, что вы изменяете внутреннее значениеstartDate, и это происходит в каждом рендеринге!. Чтобы исправить это, я рекомендую использовать служебную функцию для смещения дат, например:

      const dateOffset = (date, offset) => {
  const newDate = new Date(date);
  newDate.setDate(date.getDate() + offset)
  return newDate;
}

Затем замените ошибочную строку на:

      <span>{`${startDate.toLocaleDateString('de-DE')} - ${dateOffset(startDate, 6).toLocaleDateString('de-DE')}`}</span>

Кроме того, вы можете использовать его вhandlePreviousWeekиhandleNextWeek:

      const handlePreviousWeek = () => {
  setStartDate((currDate) => dateOffset(currDate, -7));
};

const handleNextWeek = () => {
  setStartDate((currDate) => dateOffset(currDate, 7));
};
Другие вопросы по тегам