为什么 useEffect 钩子没有按预期工作 - 它与 useState 有什么关系?

why useEffect hook not working as expected - how its related to useState?

我是 React Hook 的新手,在 useEffect 我正在创建函数,单击同一组件内的按钮时将调用该函数。但是我面临一个问题,每次它使用一步旧的道具价值,而不是新的。我不明白为什么。

如果我在状态中分配道具,它会工作正常,即使我没有使用状态值,只是设置。

Try here

const defaultCalls = () => {
    let fn = (e) => console.log('This is default click fn.');
    return {
        overrideClickCall: (newFn) => {
            fn = newFn
        },
        clickFn: (e) => {
            fn(e);
        }
    }
}

let dCalls = defaultCalls();

const anotherFn = (e, userName) => {
  console.log(userName);
}

const MyComp = props => {
  let newFn = (e) => anotherFn(e, props.userName)

  //let [state, setState] = useState(props.userName);//on uncommenting it will work fine

  useEffect(() => {
    //setState(props.userName);  //on uncommenting it will work fine    
    dCalls = defaultCalls();
    dCalls.overrideClickCall(newFn);
    console.log('override default fn')
  }, [props.userName]);

  return (
    <input type="button" onClick={dCalls.clickFn} value="Click Me" />
  )
}

export { MyComp }

让我们想想快照。每当你有一个 属性 值时,组件函数就会使用当前的 props 值执行(函数体内引用任何 props 的所有内容都将替换为实际的 prop 值)。在初始值设置之后,执行 useEffect。在您的情况下,这意味着这一行:

<input type="button" onClick={dCalls.clickFn} value="Click Me" />

是在 useEffect 运行 更新您的 defaultCalls 之前创建的。所以它有一个 clickFn.

的过时副本

如何解决它:代替 onClick={dCalls.clickFn},将其变成函数本身:onClick={(e) => dCalls.clickFn(e)}.

通过这样做,您将不会在 onClick 事件中使用任何记忆版本的 clickFn。只有当用户点击按钮时,它才会获取 clickFn,因此,获取最新版本的 clickFn

顺便说一句,我真的希望你只是在做一些学习实验,因为这段包含很多间接的代码在短期内会成为一门长枪。

我强烈推荐阅读此书:https://overreacted.io/a-complete-guide-to-useeffect/

这不是一本简短的读物,但我可以用手指数出我在开发人员文章中看到过多少次关于单个主题的如此详尽的解释。