我有这个用类编写的Pomodoro react应用程序,我想转换为钩子。
setInterval
我进行了以下更改,尽管一切似乎都可以正常工作,但并非关键的一件事是handlePlayPause
函数中的import React, { useState, useEffect } from 'react';
import SetTimer from './components/SetTimer';
import './App.css';
const App = () => {
let loop = undefined;
const [timeVariables, setTimeVariables] = useState({
breakCount: 5,
sessionCount: 25,
clockCount: 25 * 60,
currentTimer: 'Session',
isPlaying: false,
});
const {
breakCount,
sessionCount,
clockCount,
currentTimer,
isPlaying,
} = timeVariables;
useEffect(() => {
return () => {
clearInterval(loop);
};
}, []);
const handlePlayPause = () => {
const { isPlaying } = timeVariables;
if (isPlaying) {
clearInterval(loop);
setTimeVariables({ ...timeVariables, isPlaying: false });
} else {
setTimeVariables({ ...timeVariables, isPlaying: true });
loop = setInterval(() => {
console.log('Hello');
const {
clockCount,
breakCount,
sessionCount,
currentTimer,
} = timeVariables;
if (clockCount === 0) {
setTimeVariables({
...timeVariables,
currentTimer: currentTimer === 'Session' ? 'Break' : 'Session',
clockCount:
currentTimer === 'Session' ? breakCount * 60 : sessionCount * 60,
});
} else {
setTimeVariables({ ...timeVariables, clockCount: clockCount - 1 });
}
}, 1000);
}
};
const handleReset = () => {
setTimeVariables({
breakCount: 5,
sessionCount: 25,
clockCount: 25 * 60,
currentTimer: 'Session',
isPlaying: false,
});
clearInterval(loop);
};
const convertTime = (count) => {
const minutes = Math.floor(count / 60);
let seconds = count % 60;
seconds = seconds < 10 ? `0${seconds}` : `${seconds}`;
return `${minutes}:${seconds}`;
};
const handleBreakDecrease = () => {
const { breakCount } = timeVariables;
if (breakCount >= 2) {
setTimeVariables({ ...timeVariables, breakCount: breakCount - 1 });
}
};
const handleBreakIncrease = () => {
const { breakCount } = timeVariables;
setTimeVariables({ ...timeVariables, breakCount: breakCount + 1 });
};
const handleSessionDecrease = () => {
const { sessionCount } = timeVariables;
if (sessionCount >= 2) {
setTimeVariables({
...timeVariables,
sessionCount: sessionCount - 1,
clockCount: (sessionCount - 1) * 60,
});
}
};
const handleSessionIncrease = () => {
const { sessionCount } = timeVariables;
setTimeVariables({
...timeVariables,
sessionCount: sessionCount + 1,
clockCount: (sessionCount + 1) * 60,
});
};
const breakProps = {
title: 'Break Length',
count: breakCount,
handleDecrease: handleBreakDecrease,
handleIncrease: handleBreakIncrease,
};
const sessionProps = {
title: 'Session Length',
count: sessionCount,
handleDecrease: handleSessionDecrease,
handleIncrease: handleSessionIncrease,
};
return (
<div>
<div className='flex'>
<SetTimer {...breakProps} />
<SetTimer {...sessionProps} />
</div>
<div className='clock-container'>
<h1>{currentTimer}</h1>
<span>{convertTime(clockCount)}</span>
<div className='flex'>
<button onClick={handlePlayPause}>
{isPlaying ? (
<i className={`fas fa-pause`}></i>
) : (
<i className='fas fa-play'></i>
)}
</button>
<button onClick={handleReset}>
<i className='fas fa-sync-alt'></i>
</button>
</div>
</div>
</div>
);
};
export default App;
函数仅运行一次。我不知道为什么!
import React, { useState, useEffect } from 'react';
import SetTimer from './components/SetTimer';
import './App.css';
const App = () => {
console.log('rendered');
let loop = undefined;
// const [loop, setLoop] = useState(undefined);
const [breakCount, setBreakCount] = useState(5);
const [sessionCount, setSessionCount] = useState(25);
const [clockCount, setClockCount] = useState(25 * 60);
const [currentTimer, setCurrentTimer] = useState('Session');
const [isPlaying, setIsPlaying] = useState(false);
// const [timeVariables, setTimeVariables] = useState({
// breakCount: 5,
// sessionCount: 25,
// clockCount: 25 * 60,
// currentTimer: 'Session',
// isPlaying: false,
// });
// const {
// breakCount,
// sessionCount,
// clockCount,
// currentTimer,
// isPlaying,
// } = timeVariables;
// useEffect(() => {
// // setClockCount(
// // currentTimer === 'Session' ? sessionCount * 60 : breakCount * 60
// // );
// return () => {
// clearInterval(loop);
// };
// }, []);
const handlePlayPause = () => {
// const { isPlaying } = timeVariables;
if (isPlaying) {
console.log(loop, isPlaying);
clearInterval(loop);
setIsPlaying(false);
} else {
loop = setInterval(() => {
console.log(loop, isPlaying);
setIsPlaying(true);
// const {
// clockCount,
// breakCount,
// sessionCount,
// currentTimer,
// } = timeVariables;
if (clockCount === 0) {
setCurrentTimer(currentTimer === 'Session' ? 'Break' : 'Session');
setClockCount(
currentTimer === 'Session' ? breakCount * 60 : sessionCount * 60
);
// setTimeVariables({
// ...timeVariables,
// currentTimer: currentTimer === 'Session' ? 'Break' : 'Session',
// clockCount:
// currentTimer === 'Session' ? breakCount * 60 : sessionCount * 60,
// });
} else {
setClockCount((clockCount) => clockCount - 1);
// setTimeVariables({ ...timeVariables, clockCount: clockCount - 1 });
}
}, 1000);
}
};
const handleReset = () => {
setBreakCount(5);
setSessionCount(25);
setClockCount(25 * 60);
setCurrentTimer('Session');
setIsPlaying(false);
// setTimeVariables({
// breakCount: 5,
// sessionCount: 25,
// clockCount: 25 * 60,
// currentTimer: 'Session',
// isPlaying: false,
// });
clearInterval(loop);
};
const convertTime = (count) => {
const minutes = Math.floor(count / 60);
let seconds = count % 60;
seconds = seconds < 10 ? `0${seconds}` : `${seconds}`;
return `${minutes}:${seconds}`;
};
const handleBreakDecrease = () => {
// const { breakCount } = timeVariables;
if (breakCount >= 2) {
setBreakCount(breakCount - 1);
// setTimeVariables({ ...timeVariables, breakCount: breakCount - 1 });
}
};
const handleBreakIncrease = () => {
// const { breakCount } = timeVariables;
setBreakCount(breakCount + 1);
// setTimeVariables({ ...timeVariables, breakCount: breakCount + 1 });
};
const handleSessionDecrease = () => {
// const { sessionCount } = timeVariables;
if (sessionCount >= 2) {
setSessionCount(sessionCount - 1);
setClockCount((sessionCount - 1) * 60);
// setTimeVariables({
// ...timeVariables,
// sessionCount: sessionCount - 1,
// clockCount: (sessionCount - 1) * 60,
// });
}
};
const handleSessionIncrease = () => {
setSessionCount(sessionCount + 1);
setClockCount((sessionCount + 1) * 60);
// const { sessionCount } = timeVariables;
// setTimeVariables({
// ...timeVariables,
// sessionCount: sessionCount + 1,
// clockCount: (sessionCount + 1) * 60,
// });
};
const breakProps = {
title: 'Break Length',
count: breakCount,
handleDecrease: handleBreakDecrease,
handleIncrease: handleBreakIncrease,
};
const sessionProps = {
title: 'Session Length',
count: sessionCount,
handleDecrease: handleSessionDecrease,
handleIncrease: handleSessionIncrease,
};
return (
<div>
<div className='flex'>
<SetTimer {...breakProps} />
<SetTimer {...sessionProps} />
</div>
<div className='clock-container'>
<h1>{currentTimer}</h1>
<span>{convertTime(clockCount)}</span>
<div className='flex'>
<button onClick={handlePlayPause}>
{isPlaying ? (
<i className={`fas fa-pause`}></i>
) : (
<i className='fas fa-play'></i>
)}
</button>
<button onClick={handleReset}>
<i className='fas fa-sync-alt'></i>
</button>
</div>
</div>
</div>
);
};
export default App;
更新:带有各个状态变量
{{1}}
答案 0 :(得分:1)
两个版本之间非常明显的区别是 在前者中,循环处于状态。 但是在后者中,循环只是一个变量。
您可能还希望使用State进行循环。但是,我强烈反对将useState与对象(和数组)一起使用。比较浅,所以有时可能不正确。
我知道当您必须为每个字段使用State时感到沮丧。看一下useReducer。检查这篇文章。这可能会有所帮助。 https://dev.to/max_frolov_/react-hooks-usereducer-complex-state-handling-243k