React State value not updated in Arrow functional component

大憨熊 提交于 2021-02-11 12:41:07

问题


React state value not updated in the console but it is updated in the view.

This is my entire code

import React, { useEffect, useState } from 'react';

const Add = (props) => {
    console.log("a = ", props.a)
    console.log("b = ", props.b)
    const c = props.a+props.b;
    return (
        <div>
            <p><b>{props.a} + {props.b} = <span style={{'color': 'green'}}>{c}</span></b></p>
        </div>
    )
}

// export default React.memo(Add);

const AddMemo = React.memo(Add);

const MemoDemo = (props) => {

    const [a, setA] = useState(10)
    const [b, setB] = useState(10)
    const [i, setI] = useState(0);

    
    useEffect(() => {
        init()
        return () => {
            console.log("unmounting...")
        }
    }, [])

    const init = () => {
        console.log("init", i)
        setInterval(()=>{
            console.log("i = ", i)
            if(i == 3){
                setA(5)
                setB(5)
            }else{
                setA(10)
                setB(10)
            }
            setI(prevI => prevI+1)
        }, 2000)
    }

    return (
        <div>
            <h2>React Memo - demo</h2>
            <p>Function returns previously stored output or cached output. if inputs are same and output should same then no need to recalculation</p>
    <b>I= {i}</b>
            <AddMemo a={a} b={b}/>
        </div>    
    );
}   

export default MemoDemo;

Please check this image

Anyone please explain why this working like this and how to fix this


回答1:


The problem is as you initialized the setInterval once so it would reference to the initial value i all the time. Meanwhile, React always reference to the latest one which always reflect the latest value on the UI while your interval is always referencing the old one. So the solution is quite simple, just kill the interval each time your i has changed so it will reference the updated value:

React.useEffect(() => {
    // re-create the interval to ref the updated value
    const id = init();
    return () => {
      // kill this after value changed
      clearInterval(id);
    };
     // watch the `i` to create the interval
  }, [i]);

  const init = () => {
    console.log("init", i);
    // return intervalID to kill
    return setInterval(() => {
      // ... 
    });
  };



回答2:


In callback passed to setInterval you have a closure on the value of i=0.

For fixing it you can use a reference, log the value in the functional update or use useEffect:

// Recommended
useEffect(() => {
  console.log(i);
}, [i])


const counterRef = useRef(i);
setInterval(()=> {
  // or
  setI(prevI => {
    console.log(prevI+1);
    return prevI+1;
  })

  // or 
  conosole.log(counterRef.current);
}, 2000);


来源:https://stackoverflow.com/questions/63554617/react-state-value-not-updated-in-arrow-functional-component

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