为什么useState提早调用我的函数

时间:2019-06-25 16:23:41

标签: javascript reactjs react-hooks

我有一个与此等效的组件:

const PickAShell = () => {
    const [functionToRun, setFunctionToRun] = useState(() => {});
    const [shellPicked, setShellPicked] = useState(0);
    const shells = [1,2,3,4,5];

    const pickShellFn = (shellNumber, onConfirm) => {
        setFunctionToRun(onConfirm);
        setShellPicked(shellNumber);
    }
    const win = () => setShellPicked(0)
      && alert('You Win');
    const lose = (shellNumber) => setShellPicked(0)
      && alert('nothing under shell '+shellNumber)
    return (
    <div>
        {shells.map(shellNumber => {
            const clickHandler = shellNumber%2?
                () => pickShellFn(shellNumber, () => win())
              : () => pickShellFn(shellNumber, () => lose(shellNumber));
            return <Button onClick={clickHandler}>{`pick shell number ${shellNumber}`}</Button> 
     }) }
    {shellPicked? (<Button onClick={functionToRun}>Reveal Shell</Button>): null}
    </div>
    )
}

我所看到的是,当我运行它时,我单击了等效的“ pick shell number X”(选择壳号X)按钮,它会尽早运行功能(赢/输)。

在chrome开发工具中,它正在调用“ setFunctionToRun”并立即调用该函数(丢失)。

我期望的是,单击说“ pick shell number 2”按钮后,应该将functionToRun设置为() => win()粗箭头功能。然后只有在单击“显示外壳”按钮时,它才能调用任何东西。

1 个答案:

答案 0 :(得分:-1)

解决方案是使clickHandler像这样:

const clickHandler = shellNumber%2?
            () => pickShellFn(shellNumber, () => () => win())
          : () => pickShellFn(shellNumber, () => () => lose(shellNumber));

现在,当调用函数时,它会返回内部函数,可以通过显示按钮调用。

这是因为useState可以称为with a function

setPartOfState(prevState => doSomethingWith(previousState))

这意味着替代方法是致电:

setFunctionToRun(() => onConfirm);

使用相同的签名,但不使用先前的状态或调用onConfirm。如果不存在该匿名函数,那么它将在此时调用onConfirm而不是直接传入它。