Search code examples
reactjsscopemailto

How do I make the mailto: subject and body tags change when I type in them in React


I am making a contact page for my portfolio and I wanted to add a small email form that just uses an anchor tag with a mailto inside of it to send an email. Inside the form you can add a title and a body and at the bottom there is an anchor tag with a mailto property that should change whenever I type something in the form.

Image of the email form

When I hover over the anchor tag it previews the mailto, which in this case is correct because I haven't added any text myself.

Image of link preview on the anchor tag

The issue I am running into is when I do add text, it still says the mailto is undefined.

Image of the email form with text Image of the link preview still showing undefined

I tried using sessionStorage to update the text, but then the anchor tag only gets the correct data after I reload the page.

Is there any way for this to work so I can type some text in the form, and then click the 'Send' button and have it update the text without needing a refresh? I am getting stuck.

Below here is the code for the form, I use React and Tailwind.

      function contact() {
      return (
        let mailTitle;
        let mailBody;
        return (
            <SiteContainer>
                <>
                    <div className="md:col-span-2 row-span-3 bg-opacity-50 bg-white dark:bg-white/5 rounded-md p-4 border border-zinc-800/50">
                        <h1 className="font-bold text-sm dark:text-slate-500 mb-1">SUBJECT</h1>
                        <input
                            placeholder="How's it going?"
                            type="text"
                            onChange={() => {
                                mailTitle = event.target.value;
                            }}
                            className="w-full p-2 mb-4 rounded-md bg-slate-300/50 dark:bg-slate-200/5 text-sm placeholder:text-gray-600 dark:placeholder:text-slate-200/20"
                        />

                        <h1 className="font-bold text-sm dark:text-slate-500 mb-1">BODY</h1>
                        <textarea
                            onChange={() => {
                                mailBody = event.target.value;
                            }}
                            placeholder="Tell me about your day."
                            className="w-full p-2 h-36 mb-4 rounded-md bg-slate-300/50 dark:bg-slate-200/5 text-sm placeholder:text-gray-600 dark:placeholder:text-slate-200/20"
                        />

                        <div className="w-full flex flex-row justify-between items-center">
                            <p className="text-gray-900 dark:text-gray-300 text-sm"></p>

                            <a
                                target="_blank"
                                href={`mailto:westerdijk@pm.me?subject=${mailTitle}&body=${mailBody}`}
                                className="border border-gray-800 hover:bg-gray-200 dark:border-indigo-600/80 dark:bg-indigo-600/70 dark:hover:bg-indigo-500/70 flex flex-row items-center justify-center rounded-full px-5 py-2 text-sm font-medium transition-colors duration-75"
                            >
                                <span className="mt-[2px]">Send</span>
                            </a>
                        </div>
                    </div>
                </>
            </SiteContainer>
          )}

I tried using sessionStorage to set the data in a handler and then get the data again in the anchor tag, this worked only half as I had to refresh the page for the anchor tag to fetch the actual correct data. If I didn't reload the page the anchor tag would only fetch undefined, or the text from the previous form submission.


Solution

  • You can use react state (useState hook) for the local data in the component, in your case title and body.

    use useState hook inside functional component, before return

    function contact() {
     const [mailTitle, setmailTitle] = useState('');
     const [mailBody, setmailBody] = useState('');
     
     return(....)
    
    }
    

    set state on input onChange

    // set title
    onChange={() => setmailTitle(event.target.value)}
    
    // set body
    onChange={() => setmailBody(event.target.value)}
    

    on a tag use like this:

    href={`mailto:westerdijk@pm.me?subject=${mailTitle}&body=${mailBody}`}