我想将旧的类组件转换为功能性组件,但是useEffect
.
旧类组件:
state = {
seconds: this.props.seconds,
minutes: this.props.minutes,
}
componentDidMount() {
/* IF GAME IS NOT PLAYED ONCE AND ROUTE IS NOT CHANGED THEN START TIMER */
if(this.props.gameComplete === false && this.props.gameOver === false){
this.startTimer();
}
}
startTimer() {
this.timer = setInterval(this.tick.bind(this), 1000)
}
componentWillUnmount() {
clearInterval(this.timer);
}
此代码完美运行(我无法显示整个组件,因为它太大了)。
我写了一个这样的功能版本:
let [seconds, setSeconds] = useState(props.seconds);
let [minutes, setMinutes] = useState(props.minutes);
let [timer,setTimer] = useState(null);
useEffect(() => {
/* IF GAME IS NOT PLAYED ONCE AND ROUTE IS NOT CHANGED THEN START TIMER */
if(props.gameComplete === false && props.gameOver === false){
const startTimer = () => {
setTimer(timer = setInterval(tick, 1000));
}
startTimer();
}
return () => {
clearInterval(timer);
}
}, []);
此代码产生以下警告
'timer'
从 React Hook useEffect 内部对变量的赋值将在每次渲染后丢失。要随着时间的推移保留该值,请将其存储在 useRef Hook 中并将可变值保留在“.current”属性中。否则,您可以直接在 useEffect react-hooks/exhaustive-deps 中移动此变量
是的,我用英语理解,每次渲染后,钩子内的分配都会丢失,嗯,然后如果我想使用componentDidMount
上面在此代码的类版本中编写的生命周期替代方案,那么在哪里分配。
看不懂的第二个版本
如果你这样写:
useEffect(() => {
/* IF GAME IS NOT PLAYED ONCE AND ROUTE IS NOT CHANGED THEN START TIMER */
if(props.gameComplete === false && props.gameOver === false){
startTimer();
}
return () => {
clearInterval(timer);
}
}, []);
const startTimer = () => {
setTimer(timer = setInterval(tick, 1000));
}
它产生以下错误:
React Hook useEffect 缺少依赖项:“props.gameComplete”、“props.gameOver”、“startTimer”和“timer”。要么包含它们,要么删除依赖数组 react-hooks/exhaustive-deps
我不想将useEffect
来自 props 的变量和数据写在一个空数组中,它们应该只工作一次。
我该如何解决这个问题?我做错了什么?
UPD。
类中的tick函数
tick() {
if(this.props.start === true){
let {seconds,minutes} = this.state;
this.setState({seconds:(seconds + 1)});
if(seconds === 60){
this.setState({seconds:(seconds = 0)});
this.setState({minutes:(minutes + 1)});
if(minutes === 60){
this.setState({minutes:(minutes = 0)});
}
}
}
}
新功能tick
const tick = () => {
if(props.start === true){
setSeconds(seconds + 1);
if(seconds === 60){
setSeconds(seconds = 0);
setMinutes(minutes + 1);
if(minutes === 60){
setMinutes(minutes = 0);
}
}
}
}
见这里https://repl.it/@MikePodgorniy/hookTest
如果是这样呢?可以有很多解决方案,只有几个。问题是tick必须作为依赖添加或在useEffect中声明,而不是在useEffect中使用赋值和外部函数。
常见问题解答中有详细说明,还有很多要强调的内容: https ://reactjs.org/docs/hooks-faq.html#what-can-i-do-if-my-effect-dependencies-change-too-often