Satyam Saurabh
Satyam Saurabh

Reputation: 668

How to trigger a custom hook on onClick event in react

I want to call a custom hook that will send a email on clicking a button.

customHook.ts

async function sendEmail(userName: string, userEmail: string, userPhone: string) {

  const mailToUser = {
    to: userEmail,
    subject: mail.subject,
    body: mail.body,
  };

  await fetch(`/api/sendEmail`, {
    method: `POST`,
    headers: { 'Content-Type': `application/json` },
    body: JSON.stringify(mailToUser),
  });
  
  console.log(mailToUser);
}

export default sendEmail;

This is the custom hook file that needs to be call to send the mail when the button is clicked

contact.tsx

import sendEmail from 'src'

export const Contact = (props:any) {
  const userName = `Name`;
  const userEmail = `email`;
  const userPhone = `333333333`;

  return (
    <button onClick={() => sendEmail(userName, userEmail, userPhone)}>Contact</button>
  )
}

The error that comes when I click the button is:

**Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:**

Upvotes: 7

Views: 11073

Answers (3)

Arun Ramachandran
Arun Ramachandran

Reputation: 1372

It doesn't necessarily needs to be a custom hook in this case, but in case if you want to stick this with the approach, we can try to return a function from your customHook which invokes the API call.

May be this is how we can tackle this:

useSendEmail.ts

    const useSendEmail = () => { 

        const sendEmail = async(userName: string, userEmail: string, userPhone: string) { 
             const mailToUser = {
                 to: email,
                 subject: subject,
                 body: body
             }; 

             try { 
                 await fetch(`/api/sendEmail`, {
                     method: `POST`,
                     headers: { 'Content-Type': `application/json` },
                     body: JSON.stringify(mailToUser),
                 });
             } catch (error) { 
                 // Include your error handling here. 
                 console.log(error);
             }
        } 

        return { sendEmail };
    
    }

Now, you can use it in your component in this way:

contact.tsx

    import { useSendEmail } from './useSendEmail.ts';
    
    export const Contact = (props:any) {
       const { sendEmail } = useSendEmail(); // Receiving the function from hook here. 
       const userName = `Name`;
       const userEmail = `email`;
       const userPhone = `333333333`;
        
       const onClickHandler = () => {
          sendEmail(userName, userEmail, userPhone)
       }

       return (
           <button onClick={onClickHandler}>Contact</button>
       )
     }

Upvotes: 0

Pradip Dhakal
Pradip Dhakal

Reputation: 1962

You can't use the hook directly like error said, but in your case, this is normally a method, This is not a hook.

Basically hook can be useful if you are managing some sort of state/context inside it to manage your application workflow and data. But if you simply want to send email only then you dont need any kind of hook for that. You can simply create a method and call that method.

Like in here in example:

// app.js
const sendEmail = async (email, subject, body) => {
  const mailToUser = {
    to: email,
    subject: subject,
    body: body
  };
  await fetch(`/api/sendEmail`, {
    method: `POST`,
    headers: { "Content-Type": `application/json` },
    body: JSON.stringify(mailToUser)
  });
  console.log(mailToUser);
};

export default function App() {
  return (
    <div className="App">
      <button onClick={() => sendEmail("[email protected]", "subject", "body")}>
        Send Email
      </button>
    </div>
  );
}

But if you're trying to implement a hook, you can simply do like that:

// useEmail.js
const useEmail = () => {
  const sendEmail = async (email, subject, body) => {
    const mailToUser = {
      to: email,
      subject: subject,
      body: body
    };
    await fetch(`/api/sendEmail`, {
      method: `POST`,
      headers: { "Content-Type": `application/json` },
      body: JSON.stringify(mailToUser)
    });
    console.log(mailToUser);
  };

  return { sendEmail };
};

export default useEmail;

and in your component you can implement it:

// app.js
import useEmail from "./hook/sendEmail";

export default function App() {
  const { sendEmail } = useEmail();
  return (
    <div className="App">
      <button onClick={() => sendEmail("[email protected]", "subject", "body")}>
        Send Email
      </button>
    </div>
  );
}

Upvotes: 13

alishi973
alishi973

Reputation: 65

Its seems customHook.ts is not actually a hook, Read Hooks rules at React hook Rules

Upvotes: 0

Related Questions