[英]Why does my counter value increase before it starts to decrease on click - reactjs
I'm making an attendance form where teachers can mark who's absent and not and check who was absent the previous days.我正在制作出勤表,教师可以在其中标记谁缺席和未缺席,并检查前几天谁缺席。 I have the current date at the top and button which allows it to change the date forward and back.我在顶部有当前日期和按钮,它允许它向前和向后更改日期。 However, when I try to increase the value it works fine, but then when I decrease it increases by one first and then decreases after every click.但是,当我尝试增加该值时,它可以正常工作,但是当我减少它时,它首先增加一,然后在每次点击后减少。
const [date, setDate] = useState()
var today = new Date();
var dd = parseInt(String(today.getDate()).padStart(2, '0'));
var mm = String(today.getMonth() + 1).padStart(2, '0'); //January is 0!
var yyyy = today.getFullYear();
today = dd + '/' + mm + '/' + yyyy;
useEffect(() => {
setDate(today)
}, [])
const[newDay, setNewDay] = useState(dd)
const changeToTomorrow = () => {
setNewDay(newDay + 1)
setDate(newDay + '/' + mm + '/' + yyyy)
console.log(date)
}
const changeToYesterday = () => {
setNewDay(newDay - 1)
setDate(newDay + '/' + mm + '/' + yyyy)
}
return (
<div className="attendance-today-container">
<h1>Daily attendance</h1>
<div className='change-date-container'>
<div className='change-date'>
<i class="fas fa-arrow-left" onClick={changeToYesterday}></i>
<p>{date}</p>
<i class="fas fa-arrow-right" onClick={changeToTomorrow}></i>
</div>
</div>
When you update a state using setNewDay(newDay + 1)
the newDay
variable is not immediately updated.当您使用setNewDay(newDay + 1)
更新 state 时,不会立即更新newDay
变量。 So when you do setDate(newDay + '/' + mm + '/' + yyyy)
you still use the old value of newDay
to update date
.因此,当您执行setDate(newDay + '/' + mm + '/' + yyyy)
时,您仍然使用newDay
的旧值来更新date
。
You have initial state newDay = 10
date = 10/xx/xx
, then you click on increase button and the next code is executed.您有初始 state newDay = 10
date = 10/xx/xx
,然后单击增加按钮并执行下一个代码。 setNewDay(10 + 1)
setDate(10 + '/' + mm + '/' + yyyy)
setNewDay(10 + 1)
setDate(10 + '/' + mm + '/' + yyyy)
After react renders component with a new state you got newDay = 11
date = 10/xx/xx
on the next click to increase you would get setNewDay(11 + 1)
setDate(11 + '/' + mm + '/' + yyyy)
在使用新的 state 渲染组件后,您在下一次单击以增加时会得到newDay = 11
date = 10/xx/xx
您将得到setNewDay(11 + 1)
setDate(11 + '/' + mm + '/' + yyyy)
So you date
variable update is always one step behind.所以你的date
变量更新总是落后一步。
You should do something like你应该做类似的事情
let nextDay = newDay + 1
setNewDay(nextDay)
setDate(nextDay + '/' + mm + '/' + yyyy)
in both functions在这两个功能中
You are trying to set two states in a row while those are asynchronous and might not give you the updated value of newDay by the time you set date.您正在尝试连续设置两个状态,而这些状态是异步的,并且可能不会在您设置日期时为您提供 newDay 的更新值。
A fast fix can be as follows (I rearrange the code a bit with spacing):快速修复可以如下(我用间距重新排列代码):
import {useState, useEffect} from "react";
export default function SomeComponent() {
const [date, setDate] = useState()
var today = new Date();
var dd = parseInt(String(today.getDate()).padStart(2, '0'));
var mm = String(today.getMonth() + 1).padStart(2, '0'); //January is 0!
var yyyy = today.getFullYear();
today = dd + '/' + mm + '/' + yyyy;
useEffect(() => {
setDate(today)
}, [])
const[newDay, setNewDay] = useState(dd)
const changeToTomorrow = () => {
const updateDay = newDay + 1
setNewDay(updateDay)
setDate(updateDay + '/' + mm + '/' + yyyy)
console.log(date)
}
const changeToYesterday = () => {
const updateDay = newDay - 1
setNewDay(updateDay)
setDate(updateDay + '/' + mm + '/' + yyyy)
}
return (
<div className="attendance-today-container">
<h1>Daily attendance</h1>
<div className='change-date-container'>
<div className='change-date'>
<i class="fas fa-arrow-left" onClick={changeToYesterday}></i>
<p>{date}</p>
<i class="fas fa-arrow-right" onClick={changeToTomorrow}></i>
</div>
</div>
</div>
);
}
Calculate the updated date first in a new variable and then set it to both states:首先在新变量中计算更新日期,然后将其设置为两种状态:
const changeToTomorrow = () => {
const updateDay = newDay + 1
setNewDay(updateDay)
setDate(updateDay + '/' + mm + '/' + yyyy)
console.log(date)
}
const changeToYesterday = () => {
const updateDay = newDay - 1
setNewDay(updateDay)
setDate(updateDay + '/' + mm + '/' + yyyy)
}
May I suggest a different approach, as well as a different organization of the code?我可以建议一种不同的方法,以及不同的代码组织吗?
const { useState, useEffect, useCallback } = React; // utility function (not part of the component) function formatDate(date, format = 'dd/mm/yyyy') { const addLeadingZero = num => { return num < 10? `0${num}`: num.toString(); } const dd = addLeadingZero(date.getDate()); const mm = addLeadingZero(date.getMonth() + 1); const yyyy = date.getFullYear().toString(); return format.replace('dd', dd).replace('mm', mm).replace('yyyy', yyyy); } // This constant is not strictly necessary but I think it makes the code more readable const ONE_DAY_MSEC = 86400000; // Component const MyComponent = () => { const [date, setDate] = useState(new Date()); // date as a date const [dispDate, setDispDate] = useState(formatDate(new Date())); // date as a formatted string useEffect(() => { setDispDate(formatDate(date)) }, [date, setDispDate]); const handleNextDayClick = useCallback(() => { setDate((current) => new Date(current.getTime() + ONE_DAY_MSEC)) }, [setDate]); const handlePrevDayClick = useCallback(() => { setDate((current) => new Date(current.getTime() - ONE_DAY_MSEC)) }, [setDate]); return ( <div> <div>Date: {dispDate}</div> <button onClick={handlePrevDayClick}>prev day</button> <button onClick={handleNextDayClick}>next day</button> </div> ); } ReactDOM.render(<MyComponent />, document.getElementById('App'));
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script> <div id="App" />
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.