所以,我有一个带有几个文本框(名称和计时器 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);
答案 0 :(得分:1)
以下是您需要在 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>
);
};