如何在MUI对话框组件中加载react-simple-captcha画布元素?

问题描述 投票:0回答:1

我一直在尝试为我的 React 应用程序提交表单实现 react-simple-captcha,该表单嵌套在特定页面的 MUI 对话框组件内。在验证码元素未嵌套在对话框组件内的其他页面上,它可以正常工作。但是,对于验证码嵌套在 Dialog 元素内的特定页面,页面变为空白并且控制台返回错误:

Uncaught TypeError: Cannot read properties of null (reading 'getContext') at loadCaptchaEnginge

对话框组件代码如下所示:

import { useEffect, useState } from "react";
import { loadCaptchaEnginge, LoadCanvasTemplateNoReload, validateCaptcha } from "react-simple-captcha";
import Dialog from "@mui/material/Dialog";
import IconButton from "@mui/material/IconButton";
import RefreshIcon from "@mui/icons-material/Refresh";
// some other imports

const FormDialog = ({ open, setOpen }) => {
  //some states & variables declarations
  
  const handleSubmit = () => {
    //form submit event function
  }

  useEffect(() => {
    loadCaptchaEnginge(6, "#13baba", "#f5f5f5");
  }, []);

  return (
    <Dialog open={open} onClose={() => setOpen(false)}>
      <form onSubmit={handleSubmit}>
        {/* other elements */}
        <LoadCanvasTemplateNoReload />
        <IconButton
          aria-label="Reload Captcha"
          size="small"
          color="primary"
          onClick={() => loadCaptchaEnginge(6, "#13baba", "whitesmoke");}}
        >
          <RefreshIcon />
        </IconButton>
      </form>
    </Dialog>
  )
}

问题是,如果我注释掉调用

useEffect
函数的
loadCaptchaEnginge()
钩子,则页面加载成功,并且
IconButton
在单击时正常调用
loadCaptchaEnginge()
,并且验证码画布元素成功重新加载。

对于上下文,以下是包含调用 FormDialog 组件的按钮的父组件代码:

import { useState } from "react";
import FormDialog from "./FormDialog";
import Button from "@mui/material/Button"
// some other imports

const PageLayout = () => {
  const [dialogOpen, setDialogOpen] = useState(false);

  return (
    <>
      {/* some other elements */}
      <Button
        variant="contained"
        onClick={() => setDialogOpen(true)}
      >
        Apply Now
      </Button>
      <FormDialog
        open={dialogOpen}
        setOpen={setDialogOpen}
      />
    </>
  )
}

经过一番搜索,我尝试使用

useRef 
hook 创建对 FormDialog 元素的引用并修改
useEffect
部分,使 FormDialog 变成这样:

const captchaRef = useRef(null);

useEffect(() => {
    const captchaEl = captchaRef.current;
    if (captchaEl) {
      loadCaptchaEnginge(6, "#13baba", "#f5f5f5");
    }
  }, []);

return (
  <Dialog open={open} onClose={() => setOpen(false)} ref={captchaRef}>
    {/* rest of the code */}
  <Dialog>
)

实现此操作后,页面不再为空白,但在 FormDialog 出现后,验证码画布仍然未呈现。只有单击验证码重新加载按钮后,验证码画布才会出现。

reactjs react-hooks material-ui dialog captcha
1个回答
0
投票

我遇到了同样的问题:MUI 对话框元素内的画布元素。 通过创建一个单独的 Canvas 组件来解决这个问题:

function Canvas({frequency, amplitude, phase}) {
      const canvasRef = useRef(null)

      useEffect(() => {
          const canvas = canvasRef.current
          const ctx = canvas.getContext("2d")
          {/* ... */}

      }, [frequency, amplitude, phase])

      return (
          <canvas ref={canvasRef} width={300} height={150}/>
      )
}

...并在返回语句中调用该组件并传递所需的道具:

<Dialog>
    <DialogContent>
        <Canvas
            props={sliderOneValue}
            amplitude={sliderTwoValue}
            phase={sliderThreeValue}
        />
    {/* ... */}
    </DialogContent>
</Dialog>
© www.soinside.com 2019 - 2024. All rights reserved.