简体   繁体   English

“ setInterval”内部的函数无法从钩子接收更新的变量

[英]Function inside “setInterval” does not recieve updated variables from hooks

In useEffect-hook I set interval, which is running function "calculateCircle". 在useEffect-hook中,我设置了运行时间间隔“ calculateCircle”的间隔。 There I do some logic, including setting state(with useState-Hook). 我在这里做了一些逻辑,包括设置状态(使用useState-Hook)。 Variables from hooks are updated, I render and see them on page, but this function keeps consolloging old values. 挂钩中的变量已更新,我在页面上进行渲染并看到它们,但是此功能始终保持旧值的一致性。

I changed my component to the class-based component (without hooks) and everything is working now. 我将组件更改为基于类的组件(不带钩子),现在一切正常。 But I wonder which is the problem using hooks. 但是我想知道使用钩子是什么问题。

const Features = () => {
 const block1 = React.createRef();
 const shadowText = React.createRef();

 const [ mouseIn, setMouseIn ] = useState(false);
 const [ xCircle, setXCircle] = useState(-50);

 const calculateCircle = () => {
    console.log('mouseIn :', mouseIn); //never changes, but in page - yes

    if (!mouseIn) {  //never skips this loop
        console.log('begin', xCircle);//always the same            
        let r = 50;
        let yCircle = Math.sqrt(r*r - xCircle*xCircle);
        if (shadowText.current) draw(xCircle, yCircle);
        setXCircle(prev => {
            console.log('xCircle:', prev);
            return prev > 50 ? -50 : prev + 1
        });            
        console.log('end', xCircle, yCircle);
    }            
} //on page I see that xCircle changes correctly

useEffect(() => {
    const cycle = setInterval(() => calculateCircle(), 1000);
    return () => {
        clearInterval(cycle);
    }
}, []);

//without hooks it works; //不带钩子就可以了;

Since calculateCircle instance is only refererrenced initially from within the useEffect hook, it takes the xCircle and mouseIn value from the closure at the time this function was created which for the setInterval is on initial call. 由于calculateCircle实例最初仅在useEffect挂钩中进行引用,因此它在创建此函数时从闭合中获取xCircle和mouseIn值,而setInterval则在初始调用时使用。

You need to pass the second argument to useEffect so that this method is created again on xCircle or mouseIn changes 您需要将第二个参数传递给useEffect,以便在xCircle或mouseIn更改上再次创建此方法。

const Features = () => {
 const block1 = React.createRef();
 const shadowText = React.createRef();

 const [ mouseIn, setMouseIn ] = useState(false);
 const [ xCircle, setXCircle] = useState(-50);

 const calculateCircle = () => {
    console.log('mouseIn :', mouseIn); //never changes, but in page - yes

    if (!mouseIn) {  //never skips this loop
        console.log('begin', xCircle);//always the same            
        let r = 50;
        let yCircle = Math.sqrt(r*r - xCircle*xCircle);
        if (shadowText.current) draw(xCircle, yCircle);
        setXCircle(prev => {
            console.log('xCircle:', prev);
            return prev > 50 ? -50 : prev + 1
        });            
        console.log('end', xCircle, yCircle);
    }            
} //on page I see that xCircle changes correctly

useEffect(() => {
    const cycle = setInterval(() => calculateCircle(), 1000);
    return () => {
        clearInterval(cycle);
    }
}, [mouseIn, xCircle]);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM