Reactjs 箭头功能组件中未更新反应状态值

Reactjs 箭头功能组件中未更新反应状态值,reactjs,Reactjs,反应状态值在控制台中未更新,但在视图中已更新 这是我的全部代码 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 (

反应状态值在控制台中未更新,但在视图中已更新

这是我的全部代码

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;
import React,{useffect,useState}来自“React”;
常量添加=(道具)=>{
console.log(“a=”,props.a)
console.log(“b=”,props.b)
常数c=道具a+道具b;
返回(
{props.a}+{props.b}={c}

) } //导出默认反应备忘录(添加); const AddMemo=React.memo(添加); const MemoDemo=(道具)=>{ 常数[a,setA]=useState(10) const[b,setB]=useState(10) const[i,setI]=useState(0); useffect(()=>{ init() return()=>{ console.log(“卸载…”) } }, []) 常量init=()=>{ console.log(“init”,i) 设置间隔(()=>{ console.log(“i=”,i) 如果(i==3){ setA(5) 挫折(5) }否则{ setA(10) 挫折(10) } setI(prevI=>prevI+1) }, 2000) } 返回( 反应备忘录-演示 函数返回以前存储的输出或缓存的输出。若输入相同,且输出应相同,则无需重新计算

I={I}


任何人请解释为什么会这样工作,以及如何在传递给
setInterval
的回调中修复此问题您对
i=0的值有一个

要修复它,您可以使用引用,在功能更新中记录该值或使用
useffect

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

问题是,当您初始化
setInterval
一次时,它将始终引用初始值
i
。同时,始终引用最新值,该值始终反映UI上的最新值,而您的间隔始终引用旧值。因此解决方案非常简单,只需杀死inte每次您的
i
发生更改时,它都会引用更新的值:

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(() => {
      // ... 
    });
  };

我使用setTimeout而不是SetInterval,如下面的useEffect(()=>{init()return()=>{console.log(“unmounting…”)},[I])const init=()=>{setTimeout(()=>{console.log(“I=”,I)if(I>=3){setA(5)setB(5)}else{setA(10)setB(10)}setI(prevI=>prevI+1)},2000)}