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

人走茶凉 提交于 2020-02-07 03:58:26

问题


In useEffect-hook I set interval, which is running function "calculateCircle". There I do some logic, including setting state(with 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;


回答1:


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.

You need to pass the second argument to useEffect so that this method is created again on xCircle or mouseIn changes

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]);


来源:https://stackoverflow.com/questions/57471987/function-inside-setinterval-does-not-recieve-updated-variables-from-hooks

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!