我正在制作这样的TimePicker
,我还有一个状态是持续时间(从开始到结束的小时数),我使用useEffect()设定了开始或持续时间更改功能时的自动更改结束时间。
当我尝试更改持续时间时就可以了
但是更改开始时间或结束时间时出现错误 这是我的代码:
useEffect(() => {
setEnd(moment(start).add(duration, 'hours'));
}, [start, duration]);
useEffect(() => {
setDuration(moment.duration(end.diff(start)).asHours());
}, [end, start]);
CodeSanBox Sample(这个问题有点不同,因为我改进了有关矩的逻辑)
更新:感谢您的所有帮助,我做到了,这是最终代码: CodeSanBox Final
答案 0 :(得分:2)
您的问题在于,您正在修改useEffect
挂钩所依赖的东西。如果您的挂钩仅应在time
更改时运行,则请勿更改挂钩中的time
,否则它将无限循环。
如果您确实需要反馈循环但又不想使其无限循环,则可以采用标准的解决方法,该布尔状态可以告诉您是否在效果钩子内调用timeChange
。
function Foo() {
const [shouldUpdate, setShouldUpdate] = useState(false);
const [time, setTime] = useState(...);
useEffect(() => {
if (shouldUpdate) {
setShouldUpdate(false);
setTime(...);
}
}, [shouldUpdate, time]);
return whatever;
}
然后setShouldUpdate(true)
应该由实际上触发状态更改的任何对象调用。
答案 1 :(得分:1)
https://codesandbox.io/s/timepicker-8mo3x?file=/src/App.js
好吧,我想我明白了;尽管它可以工作,但可以进一步重构:
import React, { useState, useEffect } from "react";
import "./styles.css";
import { TimePicker } from "antd";
import "antd/dist/antd.css";
import moment from "moment";
const HHmm = "HH:mm";
export default function App() {
const [time,setTime] = useState({
start: "",
end: "",
duration: ""
})
const onStartChange = value => {
if(time.start && time.end && time.duration) {
const diffHours = value.diff(time.end, "hours");
const diffMinutes = moment
.utc(moment(value, HHmm).diff(moment(time.end, HHmm)))
.format("mm");
setTime((time)=>({
start: value,
end: time.end,
duration: moment(`${diffHours} : ${diffMinutes}`, HHmm)
}));
} else {
setTime((time)=>({
start: value,
end: time.end,
duration: time.duration
}))
}
};
const onDurationChange = value => {
if(time.start && time.end && time.duration) {
const endToStartTime = moment(time.start)
.add(value.hours(), "h")
.add(value.minutes(), "m");
setTime((time)=>({
start: time.start,
end: endToStartTime,
duration: value
}));
} else {
setTime((time)=>({
start: time.start,
end: time.end,
duration: value
}))
}
};
const onEndChange = value => {
if(time.start && time.end && time.duration) {
const diffHours = value.diff(time.start, "hours");
const diffMinutes = moment
.utc(moment(value, HHmm).diff(moment(time.start, HHmm)))
.format("mm");
setTime((time)=>({
start: time.start,
end: value,
duration: moment(`${diffHours} : ${diffMinutes}`, HHmm)
}));
} else {
setTime((time)=>({
start: time.start,
end: value,
duration: time.duration
}))
}
};
useEffect(()=>{
if(time.start && time.end && !time.duration) {
const diffHours = time.end.diff(time.start, "hours");
const diffMinutes = moment
.utc(moment(time.end, HHmm).diff(moment(time.start, HHmm)))
.format("mm");
setTime((time)=>({
start: time.start,
end: time.end,
duration: moment(`${diffHours} : ${diffMinutes}`, HHmm)
}));
}
if(time.start && !time.end && time.duration) {
const endToStartTime = moment(time.start)
.add(time.duration.hours(), "h")
.add(time.duration.minutes(), "m");
setTime((time)=>({
start: time.start,
end: endToStartTime,
duration: time.duration
}));
}
if(!time.start && time.end && time.duration) {
const startToEndTime= moment(time.end)
.subtract(time.duration.hours(), "h")
.subtract(time.duration.minutes(), "m");
setTime((time)=>({
start: startToEndTime,
end: time.end,
duration: time.duration
}));
}
},[time])
return (
<div className="App">
<span>Start: </span>
<TimePicker value={time.start} onChange={onStartChange} format={HHmm} />
<span>Duration: </span>
<TimePicker value={time.duration} onChange={onDurationChange} format={HHmm} />
<span>End: </span>
<TimePicker value={time.end} onChange={onEndChange} format={HHmm} />
</div>
);
}