【问题标题】:Invisible reCAPTCHA disappears on page navigation in next.js app不可见的 reCAPTCHA 在 next.js 应用程序的页面导航中消失
【发布时间】:2022-09-28 21:50:49
【问题描述】:

我在 3 个单独的页面上有 reCAPTCHA。它们在第一次加载时看起来很完美。但是当我导航到另一个页面然后重新导航回该页面(具有验证码的页面)时,它们会消失。我的应用程序是单页应用程序。我正在使用下一个/链接从一页导航到另一页。

这是我的联系页面:

import { useState, useEffect, useRef } from \"react\";
import { pattern } from \"./pricing\";
import styles from \"./../styles/Contact.module.css\";
import { post } from \"../helper\";
import { CONTACT_PAGE_ACTION_EVENT } from \"../constant\";
import ClipLoader from \"react-spinners/ClipLoader\";
import ReCAPTCHA from \"react-google-recaptcha\";


function Contact({captcha_site_key}) {
  const [formData, setFormData] = useState({
    firstName: \"\",
    email: \"\",
    emailError: \"\",
    phone: \"\",
    message: \"\",
    responseText: \"\"
  });
  const recaptchaRef = useRef(null);
  const [disabled, setDisabled] = useState(true);
  const [loading, setLoading] = useState(false)

  const formDataHandler = (name, value) => {
    setFormData((prev) => {
      if (name === \"email\") {
        return {
          ...prev,
          [name]: value.trimStart(),
          [\"emailError\"]: pattern.test(value.trimStart())
            ? \"\"
            : \"That is Not a valid email\",
        };
      } else {
        return {
          ...prev,
          [name]: value.trimStart(),
        };
      }
    });
  };

  useEffect(() => {
    setDisabled(
      !(
        formData.email.length > 0 &&
        formData.firstName.length > 0 &&
        formData.message.length > 0 &&
        formData.phone.length > 0 &&
        formData.emailError.length === 0
      )
    );
  }, [formData]);
  
  const sendData = async(e) => {
    e.preventDefault();
    setLoading(true)
    const token = await recaptchaRef.current.executeAsync();
    recaptchaRef.current.reset();
    const {emailError, responseText, ...data} = formData;

    // stripping off the html from string
    const secureData = {
      firstName: data.firstName.replace(/(<([^>]+)>)/gi, \"\").replace(/[`~!@#$%^&*()_|+\\-=?;:\",.<>\\{\\}\\[\\]\\\\\\/]/gi, \'\'),
      email: data.email.replace(/(<([^>]+)>)/gi, \"\").replace(/[`~!#$%^&*()_|+\\-=?;:\",<>\\{\\}\\[\\]\\\\\\/]/gi, \'\'),
      phone: data.phone.replace(/(<([^>])>)/gi, \"\").replace(/[`~!@#$%^&*()_|\\-=?;:\",.<>\\{\\}\\[\\]\\\\\\/]/gi, \'\'),
      message: data.message.replace(/(<([^>]+)>)/gi, \"\").replace(/[`~!@#$%^&*()_|+\\-=?;:\",.<>\\{\\}\\[\\]\\\\\\/]/gi, \'\'),
      token
    }
    const result = await  post(secureData, CONTACT_PAGE_ACTION_EVENT)

    if(result.status === \'success\'){
      setFormData({
        firstName: \"\",
        email: \"\",
        emailError: \"\",
        phone: \"\",
        message: \"\",
        responseText: result?.status
      })
    }else {
      setFormData(prev => {
        return {...prev, [\'responseText\']: result?.status}
      })
    }
    setLoading(false)

  }
  return (
    <section className={styles.contact_container}>
      <ReCAPTCHA
        ref={recaptchaRef}
        size=\"invisible\"
        sitekey={captcha_site_key}
      />
      <section className={styles.contact_section}>
        <form>
          <h3> Let&apos;s Talk </h3>
          <p> Fill out the form to send us a message </p>

          {/* FirstName */}
          <div className=\"form-floating mb-3\">
            <input 
              className=\"form-control shadow-none border-dark rounded-0\" 
              id=\"floatingInput\" 
              value={formData.firstName}
              style={{ backgroundColor: loading ? \'#f1f1f1\' : \'white\' }}
              disabled={loading}
              required
              type=\"text\"
              name=\"firstName\"
              placeholder=\"First Name*\"
              onChange={(e) =>
                formDataHandler(e.target.name, e.target.value.trimStart())
              }
            />
            <label htmlFor=\"floatingInput\" className=\"text-muted\">First Name*</label>
          </div>

          {/* Email */}
          <div>
            <div className=\"form-floating\">
              <input 
                className=\"form-control shadow-none border-dark rounded-0\" 
                id=\"floatingInput\" 
                value={formData.email}
                style={{ backgroundColor: loading ? \'#f1f1f1\' : \'white\' }}
                disabled={loading}
                required
                type=\"email\"
                name=\"email\"
                placeholder=\"Email*\"
                onChange={(e) =>
                  formDataHandler(e.target.name, e.target.value.trimStart())
                }
              />
              <label htmlFor=\"floatingInput\" className=\"text-muted\">Email*</label>
            </div>
            <p> {formData.emailError} </p>
          </div>
            
          {/* Phone Number */}
          <div className=\"form-floating mb-3\">
            <input 
              className=\"form-control shadow-none border-dark rounded-0\" 
              id=\"floatingInput\" 
              value={formData.phone}
              required
              disabled={loading}
              style={{ backgroundColor: loading ? \'#f1f1f1\' : \'white\' }}
              type=\"text\"
              placeholder=\"Phone Number*\"
              name=\"phone\"
              onChange={(e) =>
                formDataHandler(e.target.name, e.target.value.trimStart())
              }
            />
            <label htmlFor=\"floatingInput\" className=\"text-muted\">Phone Number*</label>
          </div>

          {/* Phone Number */}
          <div className=\"form-floating mb-3\">
            <input 
              className=\"form-control shadow-none border-dark rounded-0\" 
              id=\"floatingInput\" 
              value={formData.message}
              required
              type=\"text\"
              disabled={loading}
              style={{ backgroundColor: loading ? \'#f1f1f1\' : \'white\' }}
              placeholder=\"Message\"
              name=\"message\"
              onChange={(e) =>
                formDataHandler(e.target.name, e.target.value.trimStart())
              }
            />
            <label htmlFor=\"floatingInput\" className=\"text-muted\">Message*</label>
          </div>
          
          {/* Send Button */}
          <button
            disabled={disabled || loading}
            style={{
              display: \'flex\',
              justifyContent: \'center\',
              alignItems: \'center\',
              opacity: disabled ? 0.5 : 1,
              backgroundColor:\"#ff6600\",
              cursor: disabled ? \"auto\" : \"pointer\",
              width: 150
            }}
            onClick={(e) => sendData(e)}
          >
            <span style={{marginRight: 5}}> Send </span> 
            <ClipLoader color={\'white\'} loading={loading} size={15} />
          </button>
          <p 
            style={{ 
              color: formData.responseText === \'error\' ? \'red\' : \'green\',
              textAlign: \'center\',
              height: 16,
              marginTop: 10
            }}
         > {formData.responseText} </p>
        </form>
      </section>
    </section>
  );
}

export async function getStaticProps() {
  return {
    props: {
      captcha_site_key: process.env.RECAPTCHA_SITE_KEY
    }
  }
}

export default Contact;

    标签: reactjs next.js react-google-recaptcha


    【解决方案1】:

    您的应用是否有与 Next 存储库匹配的 _document 文件?一旦我添加了 MyDocument 类,它就对我有用,如下所示:

    import Document from 'next/document'
    import { ServerStyleSheet } from 'styled-components'
    
    export default class MyDocument extends Document {
      static async getInitialProps(ctx) {
        const sheet = new ServerStyleSheet()
        const originalRenderPage = ctx.renderPage
    
        try {
          ctx.renderPage = () =>
            originalRenderPage({
              enhanceApp: (App) => (props) =>
                sheet.collectStyles(<App {...props} />),
            })
    
          const initialProps = await Document.getInitialProps(ctx)
          return {
            ...initialProps,
            styles: (
              <>
                {initialProps.styles}
                {sheet.getStyleElement()}
              </>
            ),
          }
        } finally {
          sheet.seal()
        }
      }
    }
    

    【讨论】:

      【解决方案2】:

      确保在 next.config.js 文件中将 reactStrictMode 设置为 false。它应该可以解决您的问题。

      【讨论】:

        猜你喜欢
        • 2013-04-17
        • 2014-05-23
        • 2019-02-08
        • 2022-08-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多