5

I'm using react-google-recaptcha for a simple contact form on Next.js. The app theme can be toggled using a button that triggers a function that appends 'dark' to html as a class and adds a variable in localStorage. How do I get the recaptcha to update with this?

The problem is to check for dark mode I need to access either window to check for html appended class or localStorage to retrieve a dark-mode value I append on theme switch. This means I can only use the componentDidMount lifecycle method which only fires once. (SSR)

I would need something that could dynamically inject the theme string when either of the above values changes and remount the component. Here is my Captcha.jsx component which I am importing into my contact.jsx page.

import React, { Component } from 'react';
import ReCAPTCHA from 'react-google-recaptcha';

export default class Captcha extends Component {
  constructor(props) {
    super(props);
    this.state = {
      theme: 'light',
    };
  }

  componentDidMount() {
    const darkmode = document.querySelector('html').classList.contains('dark');
    if (darkmode) {
      this.setState({ theme: 'dark' });
    } else {
      this.setState({ theme: 'light' });
    }
  }

  render() {
    return <ReCAPTCHA theme={this.state.theme} />;
  }
}

ReCAPTCHA theme changes on hard refresh but not when function toggle is clicked which changes everything else using :root selector when finding 'dark' appended to html.

Byron
  • 51
  • 4

1 Answers1

0

Two things to do here.

First, you need to re-mount the Recaptcha component. You can do this using the key property, providing a new key each time you change the theme will force a re-mount of the component.

constructor() {
  super(props);
  this.state = {
    theme: 'light',
    key: 0
  };
}


componentDidMount() {
    const darkmode = document.querySelector('html').classList.contains('dark');
    if (darkmode) {
      this.setState({ theme: 'dark' });
    } else {
      this.setState({ theme: 'light' });
    }
    this.setState({ key: this.state.key++ }); 
  }

render() {
    return <ReCAPTCHA key={this.state.key} theme={this.state.theme} />;
  }

Second, if enabled... disable the <React.StrictMode> in the index.js file:

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode> // delete or comment this line.
    <App />
  </React.StrictMode> // delete or comment this line.
);
Eduardo Tavarez
  • 450
  • 3
  • 10