wenlng / go-captcha

🖖 GoCaptcha is a behavior captcha, which implements click mode, slider mode, drag-drop mode and rotation mode.
http://gocaptcha.wencodes.com
Other
1.72k stars 153 forks source link

Do not support react 17 #30

Closed Cupid001 closed 7 hours ago

Cupid001 commented 13 hours ago

WX20241204-192658@2x

The error occurs when uncommenting the following code: <GoCaptcha.Slide data={slideData} ref={domRef} config={config} />

Is it due to incompatibility? Does GoCaptcha require React version 18 or above? My project is using React version 17.0.2. I'm using the Arco Design framework. Could this be the cause?

import { Form, Input, Checkbox, Link, Button, Space, } from '@arco-design/web-react';

import GoCaptcha from 'go-captcha-react'; //滑块验证码s import { FormInstance } from '@arco-design/web-react/es/Form'; import { IconLock, IconUser } from '@arco-design/web-react/icon'; import React, { useEffect, useRef, useState } from 'react'; import useStorage from '@/utils/useStorage'; import useLocale from '@/utils/useLocale'; import locale from './locale'; import styles from './style/index.module.less'; import { get, post } from '@/http/http' import ApiManager from '@/http/ApiManager'; import { CodeImageInfo, QrCodeStatus } from '@/http/types'; import { SlidePoint } from 'go-captcha-react/dist/components/Slide/meta/data'; import { SlideData, defaultSlideData } from './meta/data'; import { defaultConfig, SlideConfig } from './meta/config'; import { SlideEvent } from './meta/event';

export default function LoginForm() { const formRef = useRef(); const [errorMessage, setErrorMessage] = useState(''); const [loading, setLoading] = useState(false); const [loginParams, setLoginParams, removeLoginParams] = useStorage('loginParams');

const api = ApiManager.getInstance();

const t = useLocale(locale);

const [rememberPassword, setRememberPassword] = useState(!!loginParams);

function afterLoginSuccess(params) { // 记住密码 if (rememberPassword) { setLoginParams(JSON.stringify(params)); } else { removeLoginParams(); } // 记录登录状态 localStorage.setItem('userStatus', 'login'); // 跳转首页 window.location.href = '/'; }

function login(params) { setErrorMessage(''); setLoading(true); // api.get("/app/login/captcha/slide", {}).then((res) => { // }); get("app/login/captcha/slide", {}).then(res => { console.log(res); }) }

function onSubmitClick() { formRef.current.validate().then((values) => { console.log("------", values); // login(values); }); }

const [activeType, setActiveType] = useState(1); function changeType(type) { console.log(type); setActiveType(type); }

const [codeImageInfo, setCodeImageInfo] = useState({ qrcodeUrl: '', qrcodeId: '' }); const getLoginCode = () => { api.getLoginQrCode().then((res: CodeImageInfo) => { setCodeImageInfo(res); // 更新状态 }) }

//检查登录状态 const checkQrStatus = () => { console.log(codeImageInfo); api.checkQrStatus(codeImageInfo.qrcodeId).then((res: QrCodeStatus) => { }) }

// 读取 localStorage,设置初始值 useEffect(() => { const rememberPassword = !!loginParams; setRememberPassword(rememberPassword); if (formRef.current && rememberPassword) { const parseParams = JSON.parse(loginParams); formRef.current.setFieldsValue(parseParams); } getLoginCode(); }, [loginParams, activeType]);

useEffect(() => { // 设置定时器定期检查登录状态 if (activeType == 2) { console.log("----------", codeImageInfo.qrcodeId); // const intervalId = setInterval(() => { if (codeImageInfo.qrcodeId) { checkQrStatus(); // 每隔一段时间检查一次登录状态 } // }, 10000); // return () => clearInterval(intervalId); } // 清除定时器,避免内存泄漏 }, [codeImageInfo.qrcodeId])

const [slideData, setSlideData] = useState(defaultSlideData); const config = defaultConfig(); useEffect(() => { // 在组件挂载后调用 refresh 方法 if (domRef.current) { domRef.current.refresh(); } api.getSlideParms().then((res: any) => { const slideData: SlideData = { thumbWidth: res.tile_width, thumbHeight: res.tile_height, thumbX: res.tile_x, thumbY: res.tile_y, image: res.image_base64, thumb: res.tile_base64 } setSlideData(slideData); }); }, [])

const domRef = useRef(null);

const event: SlideEvent = { refresh: () => console.log('Captcha refreshed'), close: () => console.log('Captcha closed'), move: (x: number, y: number) => { console.log(x, y, "======拖动"); }, confirm(point, reset) { console.log(point, "点"); // reset(); }, }

return ( <div className={styles['login-form-wrapper']}>

  <GoCaptcha.Slide
    data={slideData}
    ref={domRef}
    config={config}
  />
  <div className={styles['login-form-title']}>{t['login.form.title']}</div>
  {/* <div className={styles['login-form-sub-title']}>
    {t['login.form.title']}
  </div> */}
  <div className={styles.radio_type + ` ${activeType == 1 ? styles.active1 : styles.active2}`}>
    <div
      onClick={changeType.bind(null, 1)}
      className={activeType == 1 ? styles.active : ''}
    >验证码登录</div>
    <div onClick={changeType.bind(null, 2)}
      className={activeType == 2 ? styles.active : ''}
    >扫码登录</div>
  </div>
  <div style={{ display: errorMessage == "" ? 'none' : '' }} className={styles['login-form-error-msg']}>{errorMessage}</div>
  {activeType == 1 ?
    <Form
      style={{ display: activeType == 1 ? 'block' : 'none' }}
      className={styles['login-form']}
      layout="vertical"
      ref={formRef}
      initialValues={{ userName: '', password: '' }}
    >
      <Form.Item
        validateTrigger="onSubmit"
        field="phoneNumber"
        rules={[{ required: true, message: t['login.form.phoneNumber.errMsg'] },
        { max: 11 }, // 最大 11 位
        {
          validator: (value, callback) => {
            const phonePattern = /^(?:\+?86)?1[3-9]\d{9}$/;
            // 使用正则验证手机号格式
            if (!phonePattern.test(value.trim())) {
              callback(t['login.form.phoneNumber.valiMsg']); // 使用 callback 传递错误消息
            }
          },
        }
        ]}
      >
        <Input
          maxLength="11"
          // prefix={<IconUser />}
          onChange={(value) => {
            // 只保留数字
            const filteredValue = value.replace(/[^\d]/g, '');
            formRef.current.setFieldsValue({
              phoneNumber: filteredValue,
            });
          }}
          placeholder={t['login.form.phoneNumber.placeholder']}
          onPressEnter={onSubmitClick}
        />
      </Form.Item>
      <div className={styles.flexLeft}>
        <div>
          <Form.Item
            validateTrigger="onSubmit"
            field="password"
            rules={[{ required: true, message: t['login.form.code.errMsg'] },
            { max: 11 }, // 最大 11 位
            ]}
          >
            <Input
              placeholder={t['login.form.code.placeholder']}
              onPressEnter={onSubmitClick}
              autoWidth={{ maxWidth: 300 }}
            />

          </Form.Item>
        </div>

        <button type="button">获取验证码</button>
      </div>
      {/* <div className={styles['login-form-password-actions']}>
     <Checkbox checked={rememberPassword} onChange={setRememberPassword}>
       {t['login.form.rememberPassword']}
     </Checkbox>
     <Link>{t['login.form.forgetPassword']}</Link>
   </div> */}

      <Button type="primary" className={styles.loginBtn} long onClick={onSubmitClick} loading={loading}>
        {t['login.form.login']}
      </Button>
      <Button
        type="text"
        long
        className={styles['login-form-register-btn']}
      >
        {t['login.form.register']}
      </Button>
    </Form>
    :
    <div>
      <div>请使用微信扫描二维码登录</div>
      <img src={codeImageInfo.qrcodeUrl} className={styles.codeImage} alt="" />
    </div>
  }

</div>

); }

wenlng commented 10 hours ago

React version 17 is supported, please update to v1.0.3 or greater https://github.com/wenlng/go-captcha-react/tree/v1.0.3