Еженедельное отображение заголовков 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));
};