所以,我有一个功能组件,有一对文本框(名称和计时器I/p框显示)和开始/停止按钮。
I want that;
- 当单击"开始"时,计时器框应计数并显示经过的秒数。
- 当单击Stop时,保存名称和时间以减少存储,计时器i/p框返回零。(名称/计时器的保存值作为另一个组件的一部分显示在下面)
- 当焦点在计时器框上时,计时器应该停止/暂停
- 当我们对焦/模糊计时器框时,计时器应该从该点恢复。
我已经在下面的链接中添加了我的代码到沙箱。https://codesandbox.io/s/crisil-tp7pv?file=/src/TestComponent.js
部分相关代码也在下面突出显示。从本质上讲,我想知道,如果我使用useEffect来更新计时器框?有什么改进方法的建议吗?
export const TestComponent = (props) => {
const [task, setTask] = useState({ id: 0, taskName: "", timeField: 0 });
const [stopTimerEvt, setStopTimerEvt] = useState(true);
//var timerId;
useEffect(() => {
var seconds = 0;
var interval;
if (stopTimerEvt === false) {
interval = setInterval(function () {
setTask((prevState) => {
return { ...prevState, timeField: seconds++ };
});
}, 1000);
}
return () => clearInterval(interval);
}, [stopTimerEvt]);
const startTimer = () => {
setStopTimerEvt(false);
/*
timerId = setInterval(function () {
setTask((prevState) => {
return { ...prevState, timeField: seconds++ };
});
}, 1000);
*/
};
const stopTimer = () => {
//clearInterval(timerId);
setStopTimerEvt(true);
props.saveTask(task);
setTask((prevState) => {
return { ...prevState, timeField: 0 };
});
};
const handleChange = (e) => {
setTask((prevState) => ({
...prevState,
[e.target.id]: e.target.value
}));
};
return (
<main>
<input
type="text"
id="taskName"
value={task.taskName}
onChange={handleChange}
/>
<input
type="number"
id="timeField"
value={task.timeField}
onChange={handleChange}
/>
<button id="start" onClick={startTimer}>
Start
</button>
<button id="stop" onClick={stopTimer}>
Stop
</button>
</main>
);
};
export default connect(null, { saveTask })(TestComponent);
以下是您需要在TestComponent
中进行的一些更改:
export const TestComponentNew = (props) => {
const [task, setTask] = useState({ taskName: "", timeField: 0 });
const timer = useRef();
useEffect(() => {
return () => stopTimer();
}, []);
const startTimer = () => {
timer.current = setInterval(function () {
setTask((v) => ({ ...v, timeField: +v.timeField + 1 }));
}, 1000);
};
const stopTimer = () => {
clearInterval(timer.current);
timer.current = null;
props.saveTask(task);
setTask({ taskName: "", timeField: 0 });
};
const handleChange = (e) => {
setTask((prevState) => ({
...prevState,
[e.target.id]: e.target.value
}));
};
return (
<main>
<input
type="text"
id="taskName"
value={task.taskName}
onChange={handleChange}
placeholder="task name"
/>
<input
type="number"
id="timeField"
value={task.timeField}
onChange={handleChange}
/>
<button id="start" onClick={startTimer}>
Start
</button>
<button id="stop" onClick={stopTimer}>
Stop
</button>
</main>
);
};
下面是演示:https://codesandbox.io/s/crisil-forked-pfrb3?file=/src/TestComponentNew.js
EDITED
export const TestComponentNew = (props) => {
const [task, setTask] = useState({ taskName: "", timeField: 0 });
const timer = useRef();
useEffect(() => {
return () => stopTimer();
}, []);
const startTimer = () => {
timer.current = setInterval(function () {
setTask((v) => ({ ...v, timeField: +v.timeField + 1 }));
}, 1000);
};
const stopTimer = () => {
clearInterval(timer.current);
timer.current = null;
props.saveTask(task);
setTask({ taskName: "", timeField: 0 });
};
const handleChange = (e) => {
setTask((prevState) => ({
...prevState,
[e.target.id]: e.target.value
}));
};
const handlePause = () => {
clearInterval(timer.current);
};
return (
<main>
<input
type="text"
id="taskName"
value={task.taskName}
onChange={handleChange}
placeholder="task name"
/>
<input
type="number"
id="timeField"
value={task.timeField}
onChange={handleChange}
onFocus={handlePause}
onBlur={startTimer}
/>
<button id="start" onClick={startTimer}>
Start
</button>
<button id="stop" onClick={stopTimer}>
Stop
</button>
</main>
);
};