我有一个需要使用间隔更新的计数器变量。我遇到的问题是 firstprivate(e)
无权访问组件当前状态。在寻找解决方法时,我偶然发现了 Dan Abramov 的一篇博客文章,该文章实现了一个自定义钩子来规避这个问题。
然而,在使用他的代码时,我立即遇到了这个错误:
setInterval
据我所知,我没有违反任何钩子规则,并且我使用了几种 react 站点调试方法来查看是否有重复的 react 版本。从下面的代码中是否有我不知道的钩子规则?
我唯一能想到的是错误是因为我从 Error: Invalid hook call. Hooks can only be called inside of the body of a function component.
内部调用 useInterval
。如果是这种情况,您将如何设置这样的间隔,使其在挂载时仅启动一次?
useEffect
import React, { useState, useEffect } from 'react';
import { VictoryPie } from "victory";
// styles
import styles from './logConfirmation.module.css';
// custom
import { useInterval } from "../../hooks/useInterval";
const LogConfirmation = props => {
// props
const { oldScore, newScore } = props;
// local
const [ score, setScore ] = useState(oldScore);
const [ data, setData ] = useState(null);
useEffect(() => {
const difference = 100/((newScore - (score || 0))*Math.sqrt(.01));
useInterval(()=>{
setScore(score < newScore ? score + 1 : newScore);
}, difference);
}, []);
useEffect(() => {
setData([{ x: 1, y: score }, { x: 2, y: 100 - score }]);
}, [score]);
return (
<div id='selectionModal' className={styles.container}>
<div className={styles.score}>
<div className="wellness-circle">
<div className="circle-inner d:f a-i:c">
<h2 className='t-a:c'><span className='plus'>+</span>{score.current}</h2>
</div>
<div className="circle-outer">
<VictoryPie
innerRadius={200}
cornerRadius={50}
data={data}
labels={() => null}
style={{
data: {
fill: (d) => {
let color;
if(d.y < 50) color = "#fff";
if(d.y > 49 && d.y < 76) color = "#fff";
if(d.y > 75) color = "#fff";
return d.x === 1 ? color : 'transparent';
}
}
}}
/>
</div>
</div>
</div>
<h2 className={styles.points}>[+5 Points]</h2>
<p className={styles.pointsBottom}>Total points earned for this today</p>
<div className={styles.streak}>
<div>
<h4 className={styles.streakTitle}>You're on a streak!</h4>
<p className={styles.streakTag}>[11 days straight. Nice :)]</p>
</div>
</div>
</div>
)
}
export default LogConfirmation;
useInterval.js
答案 0 :(得分:1)
由于钩子逻辑放在它自己的useEffect
里面,并且回调在useRef
的帮助下持久存储在里面,它在挂载过程中只会运行一次,这意味着你可以把钩子放在直接函数体,像这样:
const LogConfirmation = props => {
// props
const { oldScore, newScore } = props;
// local
const [ score, setScore ] = useState(oldScore);
const [ data, setData ] = useState(null);
useInterval(()=>{
setScore(score < newScore ? score + 1 : newScore);
}, 100/((newScore - (score || 0))*Math.sqrt(.01)));
// Rest of code