我正在嘗試制作一個計劃器,它具有切換月份的按鈕。我正在使用反應和狀態來存盤日期。各個月份都被正確映射,但月份之間的切換會產生一些奇怪的行為。月份更新,但日期似乎沒有更新,并且必須多次按下按鈕才能更新地圖。按下另一個按鈕然后跳轉兩個月并發生相同的行為。
const MonthView = () => {
const months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
const daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
const daysOfWeek = ["Sun", "Mon", "Tues", "Wed", "Thu", "Fri", "Sat"];
const globalDate = new Date();
// ^ switches between two months. strange behaviour. fix?
// date does not appear to actially change.
const [month, setMonth] = useState(globalDate.getMonth());
const [year, setYear] = useState(globalDate.getFullYear());
const [day, setDay] = useState(globalDate.getDate());
const [dayOfWeek, setDayOfWeek] = useState(globalDate.getDay());
const [days, setDays] = useState([]);
const [events, setEvents] = useState([]);
const [firstDayOfMonthDay, setFirstDayOfMonthDay] = useState(daysOfWeek[new Date(year, month, 1).getDay()]);
const [firstDayOfMonth, setFirstDayOfMonth] = useState(new Date(year, month, 1).getDay());
const [lastDayOfMonth, setLastDayOfMonth] = useState(new Date(year, month 1, 0).getDay());
const [lastDayOfMonthNumber, setLastDayOfMonthNumber] = useState(new Date(year, month 1, 0).getDate());
const [firstDayOfMonthNumber, setFirstDayOfMonthNumber] = useState(new Date(year, month, 1).getDate());
const updateStates = () => {
console.log("gdate: " globalDate);
setMonth(globalDate.getMonth());
setYear(globalDate.getFullYear());
setDay(globalDate.getDate());
setDayOfWeek(globalDate.getDay());
setFirstDayOfMonthDay(daysOfWeek[new Date(year, month, 1).getDay()]);
setFirstDayOfMonth(new Date(year, month, 1).getDay());
setLastDayOfMonth(new Date(year, month 1, 0).getDay());
setLastDayOfMonthNumber(new Date(year, month 1, 0).getDate());
setFirstDayOfMonthNumber(new Date(year, month, 1).getDate());
set_days();
}
const set_days = () => {
let days = [];
for (let i = 0; i < firstDayOfMonth; i ) {
days.push(null);
}
for (let i = 1; i <= lastDayOfMonthNumber; i ) {
days.push(i);
}
for (let i = 0; i < (6 - lastDayOfMonth); i ) {
days.push(i 1);
}
setDays(days);
console.log(days)
console.log(globalDate);
}
useEffect(() => {
set_days();
}, []);
return(
<>
<Table striped bordered hover size="sm" variant="light">
<thead>
<tr>
<th></th>
<th></th>
<th><Button variant="info" onClick={() => {globalDate.setMonth(globalDate.getMonth() - 1); updateStates();}}><FontAwesomeIcon icon={faAngleLeft} /></Button></th>
<th>{months[month]}</th>
<th><Button variant="info" onClick={() => {globalDate.setMonth(globalDate.getMonth() 1); updateStates();}}><FontAwesomeIcon icon={faAngleRight} /></Button></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
{daysOfWeek.map((day, index) => {
return <td key={index}>{day}</td>
}
)}
</tr>
{days.map((day, index) => {
if (index % 7 === 5) {
// MAKE CLICK ON CELL RETURN VAL and create new event on that day
// also week view and day view
// use lighthouse to test and do everything possible to decrease load time
return <tr key={index}> {days.slice(index - 5, index 2).map((day, index2) => {
return <td key={index2} onClick={() => {console.log(index index2 - 5);}}>{day}</td>
}
)}
</tr>
}
}
)}
</tbody>
</Table>
</>
)
}
uj5u.com熱心網友回復:
正如評論者 stefan 所說,我們可以大大簡化此代碼以減少出錯的可能性。您有很多從globalDate. 如果您始終可以從其他狀態計算值,則不應將其存盤為狀態。您可以簡單地將它們宣告為常量。你不再需要你的updateStates邏輯,你的set_days函式也不需要陷入useEffect困境。洗掉冗余狀態后,您真正需要的唯一狀態變數是globalDate和events。
另一個問題是您的按鈕onClick行為。當你呼叫時globalDate.setMonth(),你正在變異狀態。React 中的狀態是不可變的,應該通過創建新的狀態副本并更改您需要的部分來更新。為了解決這個問題,您可以實體化一個新Date物件,呼叫setMonth該物件,然后設定globalDate為該新物件。
以下內容簡化了您的代碼并解決了您遇到的問題:
const MonthView = () => {
const months = [
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
];
const daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
const daysOfWeek = ["Sun", "Mon", "Tues", "Wed", "Thu", "Fri", "Sat"];
const [events, setEvents] = useState([]);
const [globalDate, setGlobalDate] = useState(new Date());
const month = globalDate.getMonth();
const year = globalDate.getFullYear();
const day = globalDate.getDate();
const dayOfWeek = globalDate.getDay();
const firstDayOfMonthDay = daysOfWeek[new Date(year, month, 1).getDay()];
const firstDayOfMonth = new Date(year, month, 1).getDay();
const lastDayOfMonth = new Date(year, month 1, 0).getDay();
const lastDayOfMonthNumber = new Date(year, month 1, 0).getDate();
const firstDayOfMonthNumber = new Date(year, month, 1).getDate();
const days = (() => {
let daysArr = [];
for (let i = 0; i < firstDayOfMonth; i ) {
daysArr.push(null);
}
for (let i = 1; i <= lastDayOfMonthNumber; i ) {
daysArr.push(i);
}
for (let i = 0; i < 6 - lastDayOfMonth; i ) {
daysArr.push(i 1);
}
return daysArr;
})();
return (
<>
<Table>
<thead>
<tr>
<th></th>
<th></th>
<th>
<Button
variant="info"
onClick={() => {
const newDate = new Date();
newDate.setMonth(globalDate.getMonth() - 1);
setGlobalDate(newDate);
}}
>
<FontAwesomeIcon icon={faAngleLeft} />
</Button>
</th>
<th>{months[month]}</th>
<th>
<Button
variant="info"
onClick={() => {
const newDate = new Date();
newDate.setMonth(globalDate.getMonth() 1);
setGlobalDate(newDate);
}}
>
<FontAwesomeIcon icon={faAngleRight} />
</Button>
</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
{daysOfWeek.map((day, index) => {
return <td key={index}>{day}</td>;
})}
</tr>
{days.map((day, index) => {
if (index % 7 === 5) {
// MAKE CLICK ON CELL RETURN VAL and create new event on that day
// also week view and day view
// use lighthouse to test and do everything possible to decrease load time
return (
<tr key={index}>
{" "}
{days.slice(index - 5, index 2).map((day, index2) => {
return (
<td
key={index2}
onClick={() => {
console.log(index index2 - 5);
}}
>
{day}
</td>
);
})}
</tr>
);
}
})}
</tbody>
</Table>
</>
);
};
你有一些我留下的未使用的變數,以防你以后需要它們。它看起來像firstDayOfMonth, , 之類的一些值lastDayOfMonth,并且lastDayOfMonthNumber僅在生成days陣列的函式中使用,因此如果其他地方不需要它們,它們可能可以移動到該函式的主體中。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/494987.html
標籤:javascript 反应 日期 array.prototype.map
上一篇:如何解決adobeacrobat中的JavaScript語法錯誤?
下一篇:指定哪個欄位驗證失敗
