Śāntanu
Śāntanu

Reputation: 243

Call a GraphQL Mutation once after React component mounts

After a user creates a profile, they receive a link in their email that sends them back to the site with a verifyToken in the url. If the token matches the token that is stores in the database, their isVerified status is stored in the database with the value true.

new-profile.js

import VerifyEMail from '../components/VerifyEmail';

const NewProfilePage = props => (
  <div>
    <VerifyEMail verifyToken={props.query.verifyToken} />
  </div>
);

export default NewProfilePage;

Currently, I have this implemented and working using a form with a "Verify" button that the user must click to call the graphQL mutation, verifyEmail. Since this sets the isVerified value to true in the database, I know that everything is working as it should.

../components/VerifyEmail.js

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Mutation } from 'react-apollo';
import gql from 'graphql-tag';

const VERIFY_EMAIL_MUTATION = gql`
  mutation VERIFY_EMAIL_MUTATION($verifyToken: String!) {
    verifyEmail(verifyToken: $verifyToken) {
      isVerified
    }
  }
`;

class VerifyEmail extends Component {
  render() {
    const { verifyToken } = this.props;
    return (
      <Mutation mutation={VERIFY_EMAIL_MUTATION} variables={{ verifyToken }}>
        {verifyEmail => (
          <form
            onSubmit={async () => {
              await verifyEmail(verifyToken);
            }}
          >
            <button type="submit">Verify</button>
          </form>
        )}
      </Mutation>
    );
  }
}

VerifyEmail.propTypes = {
  verifyToken: PropTypes.string.isRequired,
};

export default VerifyEmail;

However, I really don't want to force my users to have to click a button to fire the mutation. I would like it to be called once the component loads. I have been racking my brain for a day and a half on this, tried so many things, and just can't seem to find anything that works.

I've seen some solutions using React hooks, Apollo hooks, componentDidMount, etc. My mind is just having a difficult time seeing it any more. This link had some of the best solutions that I found so far, but I couldn't figure out how to implement them... [Feature idea] Execute a mutation on mount #1939

Any help to point me in the right direction would be really appreciated. Thank you.

Upvotes: 1

Views: 2364

Answers (1)

Agney
Agney

Reputation: 19194

This is far simpler application when using React hooks:

import React, { useEffect } from "react";

function VerifyEmail({ verifyToken }) {
  const [ verifyEmail, { loading, data, error }] = useMutation(VERIFY_EMAIL_MUTATION);
  useEffect(() => {
    verifyEmail({
      variables: { verifyToken },
    });
  }, []);
  return (
    <>
      {loading && <p>Loading...</p>}
      {data && <p>Verified successfully!</p>}
      {error && <p>Error!</p>}
    </>
  )
}

If you somehow want to keep using classes, the only solution is to create a component and utilise componentDidMount of the component for this purpose.

// Current component:
<Mutation mutation={VERIFY_EMAIL_MUTATION} variables={{ verifyToken }}>
  {verifyEmail => (
    <SendEmail token={verifyToken} verify={verifyEmail} />
  )}
</Mutation>

// Send Email component
class SendEmail extends Component {
  componentDidMount() {
    const { token, verify } = this.props;
    verify(token);
  }
  render() {
    return (
      //handle loading, data and error states
    )
  }
}

Upvotes: 1

Related Questions