Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript

Killeon Patterson
Killeon Patterson
18,214 Points

How do l detect a user attempting to leave a page/close a tab/back button?

I'm attempting to alert a user from leaving the page, closing a tab, or returning to a previous window during a stripe card purchase process. How do I manage the payments so a user's behavior doesn't interrupt the intended flow if they. Thank you.

//lines 112-129 are where I tried detecting window loadings.

import React, { useState, useEffect } from 'react';
import axios from 'axios';
import CardSection from './CardSection.component';
import Modal from './modal.component';
import {injectStripe} from 'react-stripe-elements';






   const CheckoutForm = props => {



     const [name, setName] = useState("");
     const [mentionMan, setMentionMan] = useState("");
     const [commId, setCommId] = useState("");
     const [confirm, setConfirmMe] = useState(false);
     const [nono, setNono] = useState(["StripeCardError"]);
     const [openModal, setOpenModal] = useState(false);

     let barneyId = null;


   const confirmed = () => {

      const answer = {
        commId: barneyId,
        ready: "order received!"
      }

     axios.post('http://localhost:5000/users/confirmed', answer, { headers:
      {
      "this-token": localStorage.getItem("this-token")
    }
    })
    .then(res => {
      setOpenModal(false);
          deleteOrder();
       })
       .catch((error) => {
         console.log(error);
       })

     }


    const receiptMe = async () => {
    barneyId = Math.floor(Math.random() * 1001);

     const receipter = {
       yourOrder: props.adCart,
       amounter: props.amount,
       commId: barneyId
     }
     console.log(barneyId);

    await axios.post('http://localhost:5000/users/receiptme/', receipter, {  headers:
          {
            "this-token": localStorage.getItem("this-token")
           }
      })
   .then(res => console.log("You tried it..."));
   }


  const postOrder = async () => {
      const info = {
      adCart: props.adCart,
      commId: barneyId
    }
    await axios.post('http://localhost:5000/users/orders/info', info, {  headers:
          {
            "this-token": localStorage.getItem("this-token")
           }
      })
      .then(res => {
         console.log(info);
        })
        .catch((error) => {
          console.log(error);
        })
      }


      const deleteOrder = () => {

      axios.delete('http://localhost:5000/users/orders/all',  {  headers:
         {
            "this-token": localStorage.getItem("this-token")
           }
      })
      .then(response => {
       console.log("ok");
        window.location = "/status";
      })
      .catch((error) => {
        console.log(error);
      })
  }





    const handleInputChange = (event) => {
      setName(event.target.value);
  }


  const boxStuff = () => {
      console.log("Man");
  }

  const lockBox = () => {
      console.log("Wally");
  }
      const handleSubmit = async (ev) => {
       // prevent event
       // prevent event
          ev.preventDefault();


      //Attempting to detect a user leaving
       if (ev.target) {
        window.addEventListener("beforeunload", boxStuff(), {capture: true});

       } else {
       window.removeEventListener("beforeunload", lockBox(), {capture: true});

       }

       try {
         let {
           token: { id },
         } = await props.stripe.createToken({ name: name });
         let amount = props.amount;
         setOpenModal(true);
         let res = await axios.post(
           'http://localhost:5000/users/pay',
           {
             token: id,
             amount,
           },
           {
             headers: {
               'this-token': localStorage.getItem('this-token'),
             },
           },
         );
         console.log(res.data);

       let eMan = nono.filter((el) => el === res.data);
      await (eMan.length > 0) ? console.log("Card did not go through.") : receiptMe();
       if (eMan.length > 0) {
         setMentionMan('There was an error with your card.');
       } else {
         postOrder();
         confirmed();
       }
     } catch (error) {
       console.log(error);
     }


   }






    return (

      <div>
    <input
     type="string"
     value={name}
     name="name"
     placeholder=" Card Name"
     onChange={handleInputChange}
     style={{
  border: "1px",
  borderTopStyle: "hidden",
  borderRightStyle: "hidden",
  borderLeftStyle:"hidden",
  borderBottomStyle: "groove",
  borderColor: "black",
  marginBottom: "2%"}} />
      <form onSubmit={handleSubmit}>
        <CardSection/>
        <button type="submit" value="Submit" className="btn btn-outline-primary" >
        Confirm order
        </button>
      </form>
      <h3>
      Total Amount:
      </h3>
      <p>
      ${props.amount}
      </p>
      <p>{mentionMan}</p>
      {openModal && <Modal closeModal={setOpenModal} />}
      </div>



    );
  }


export default injectStripe(CheckoutForm);

2 Answers

Rohald van Merode
seal-mask
STAFF
.a{fill-rule:evenodd;}techdegree
Rohald van Merode
Treehouse Staff

Hey Killeon Patterson,

I'd suggest to checkout the Promp component that comes with React Router. This enables you to get that functionality without to much additional code. If you're using React Router v6 it's a hook called usePrompt of which you can find a nice example here

Hope this helps 🙂

Killeon Patterson
Killeon Patterson
18,214 Points

Hello Rohald van Merode

It did help. Thank you for your response : )

Steven Parker
Steven Parker
229,644 Points

The event handler should accept the event object as a parameter and include event.preventDefault(); to stop the default action (closing). Be aware that as a security measure, browsers typically will only display their own warning message, and even this might not happen if no other user interaction has occurred since the window or tab opened.

Killeon Patterson
Killeon Patterson
18,214 Points

Thank you for your reply, Steven.

"ev" is the event parameter referenced. "ev.preventDefault()" along with "ev.target" are being used inside the handleSubmit function. When I submit the payment, I'm still able to close the window/return/navigate to another page. I tested changing the references specifically to "event" and it appears to have the same results.

Steven Parker
Steven Parker
229,644 Points

The event handlers "boxStuff" and "ockBox" don't currently accept arguments or call preventDefault.
Also, when establishing the listener, only name the handler and don't call it.

Killeon Patterson
Killeon Patterson
18,214 Points
  • Steven Thank you for your reply. I got it working.