为什么在我的 React 应用程序中使用 useEffect 和 setInterval 时会出现对象错误?
Why do I get an object error when using useEffect and setInterval in my React app?
我正在使用 React 构建一个带有 start/stop 按钮的计数器。我的功能组件中的 codepen 不断出现对象错误。我已将其缩小到 useEffect 中的 setInterval 行(codepen 中的第 32 行),但我无法弄清楚它有什么问题。
代码笔:https://codepen.io/sirstevekim/pen/zYROyxj
const App = () => {
const [time, setTime] = React.useState(0);
const [isRunning, setIsRunning] = React.useState(false);
const counter = () => setTime(time + 1);
React.useEffect(() => {
const interval = null;
if (isRunning === false) {
interval = setInterval(counter, 1000);
} else {
clearInterval(interval);
}
return () => {clearInterval(interval)};
}, [isRunning]);
const handleStartStop = () => {
setIsRunning(!isRunning);
}
const handleReset = () => {
setIsRunning(false);
setTime(0);
}
return (
<div className="app">
<Timer time={time} />
<ControlButtons
handleStartStop={handleStartStop}
handleReset={handleReset}
/>
</div>
);
}
有几个问题需要更正,
- 您的计数器应该使用回调函数,否则它不会由于关闭问题而更新(它总是看到 0 并向其添加 1)。
const counter = () => setTime((prevTime) => prevTime + 1);
- 间隔应该是
let
而不是 const
因为你重新分配了它。
let interval = null;
工作演示
const Timer = (props) => {
return <div className="timer">{props.time}</div>;
};
const ControlButtons = (props) => {
return (
<div>
<button className="start-stop" onClick={props.handleStartStop}>
Start/Pause
</button>
<button className="reset" onClick={props.handleReset}>
Reset
</button>
</div>
);
};
const App = () => {
const [time, setTime] = React.useState(0);
const [isRunning, setIsRunning] = React.useState(false);
const counter = () => setTime((prevTime) => prevTime + 1);
React.useEffect(() => {
let interval = null;
if (isRunning === false) {
interval = setInterval(counter, 1000);
} else {
clearInterval(interval);
}
return () => {
clearInterval(interval);
};
}, [isRunning]);
const handleStartStop = () => {
setIsRunning(!isRunning);
};
const handleReset = () => {
setIsRunning(false);
setTime(0);
};
return (
<div className="app">
<Timer time={time} />
<ControlButtons
handleStartStop={handleStartStop}
handleReset={handleReset}
/>
</div>
);
};
ReactDOM.render(<App />, document.querySelector('.react'));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div class='react'></div>
我正在使用 React 构建一个带有 start/stop 按钮的计数器。我的功能组件中的 codepen 不断出现对象错误。我已将其缩小到 useEffect 中的 setInterval 行(codepen 中的第 32 行),但我无法弄清楚它有什么问题。
代码笔:https://codepen.io/sirstevekim/pen/zYROyxj
const App = () => {
const [time, setTime] = React.useState(0);
const [isRunning, setIsRunning] = React.useState(false);
const counter = () => setTime(time + 1);
React.useEffect(() => {
const interval = null;
if (isRunning === false) {
interval = setInterval(counter, 1000);
} else {
clearInterval(interval);
}
return () => {clearInterval(interval)};
}, [isRunning]);
const handleStartStop = () => {
setIsRunning(!isRunning);
}
const handleReset = () => {
setIsRunning(false);
setTime(0);
}
return (
<div className="app">
<Timer time={time} />
<ControlButtons
handleStartStop={handleStartStop}
handleReset={handleReset}
/>
</div>
);
}
有几个问题需要更正,
- 您的计数器应该使用回调函数,否则它不会由于关闭问题而更新(它总是看到 0 并向其添加 1)。
const counter = () => setTime((prevTime) => prevTime + 1);
- 间隔应该是
let
而不是const
因为你重新分配了它。
let interval = null;
工作演示
const Timer = (props) => {
return <div className="timer">{props.time}</div>;
};
const ControlButtons = (props) => {
return (
<div>
<button className="start-stop" onClick={props.handleStartStop}>
Start/Pause
</button>
<button className="reset" onClick={props.handleReset}>
Reset
</button>
</div>
);
};
const App = () => {
const [time, setTime] = React.useState(0);
const [isRunning, setIsRunning] = React.useState(false);
const counter = () => setTime((prevTime) => prevTime + 1);
React.useEffect(() => {
let interval = null;
if (isRunning === false) {
interval = setInterval(counter, 1000);
} else {
clearInterval(interval);
}
return () => {
clearInterval(interval);
};
}, [isRunning]);
const handleStartStop = () => {
setIsRunning(!isRunning);
};
const handleReset = () => {
setIsRunning(false);
setTime(0);
};
return (
<div className="app">
<Timer time={time} />
<ControlButtons
handleStartStop={handleStartStop}
handleReset={handleReset}
/>
</div>
);
};
ReactDOM.render(<App />, document.querySelector('.react'));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div class='react'></div>