首页 > 解决方案 > React useCallback 和 useEffect 同时搞乱了状态

问题描述

我为我的应用程序创建了一个SignaturePad,稍后会将值传递给 Formik。

问题1:

我在使用react的useEffectand功能时遇到了一些问题。useCallback以前在我添加 useEffect 之前,handleClear函数工作得很好。然而,在我添加 useEffect 之后,sigPadrefs 总是在 handleClear 中返回 null。

我不确定我的心理模型是否正确,谁能解释为什么会这样?

问题2:

然而,我意识到,在我删除[sigPad]at之后,handleClear我能够再次收到裁判。我的代码的哪一部分重新呈现以及 useCallback 如何没有意识到 sigPad 正在从 null 更改为正确的 ref?

有问题的代码:

export function Signature() {
  let sigPad = useRef(null);
  const [sig, setSig] = useState("");
  const classes = formStyles();

  useEffect(() => {
    console.log(sigPad);
    setSig(sigPad.toData());
    console.log(sigPad);
  }, [sig]);
  const handleClear = useCallback(() => {
    console.log(sigPad);
    if (sigPad) sigPad.clear();
  }, [sigPad]);

  return (
    <div className="row">
      <Grid spacing={3} container>
        <Grid item xs={12}>
          <h3 className="text-bold">Signature</h3>
        </Grid>
        <Grid item xs={12}>
          <div className="sigCanvas">
            <SignatureCanvas
              penColor="black"
              canvasProps={{ className: "sigPad" }}
              ref={ref => {
                sigPad = ref;
              }}
            />
          </div>
        </Grid>
        <Grid item xs={3}>
          <Button
            variant="contained"
            component="label"
            className={classes.instructions}
            onClick={handleClear}
          >
            Clear
          </Button>
        </Grid>
        <Grid item xs={3}>
          <Button
            component="label"
            variant="contained"
            className={classes.instructions}
          >
            Save
          </Button>
        </Grid>
      </Grid>
    </div>
  );
}

当前修复:

  const handleClear = useCallback(() => {
    console.log(sigPad);
    if (sigPad) sigPad.clear();
  });

注意:在我添加 useEffect 之前,我不必[sigPad]在我的回调中删除

标签: reactjs

解决方案


钩子按照它们被调用的顺序执行,这意味着你useEffect的优先于你的useCallback函数。此外,这[]称为依赖数组,用于创建底层结构的新实例。使用useRef时不需要这样做

ref={ref => { sigPad = ref; }}

你可以做

ref={sigPad}

并尝试移动您的useCallback上方useEffect


推荐阅读