Imagine we have a scenario where user comes to a website and has to see a pop-up or modal with some information and has to click it to see the main content.
For example, agree to Terms and Conditions, read an important warning or merely see a call to action.
But to make it less annoying, we only want to show it once to a new user and hide it for the returning users...
This can be easily done with localStorage where we can keep the data about user clicks on the pop-up.
The way it will work would be the following:
1: New user comes to the website
2: Our component renders
3: We check if we have data in localStorage about this user already clicked on the pop-up
4: If we do not have it, then in the state of component we set data displayPopUp
to be true
4a: Once user clicked to close pop-up we set localStorage to popUpClickd to be true and state displayPopUp
to be false
5: If we do have it we set state to displayPopUp
to be false
First in our react component we will import modal:
// import useEffect and useState
import { useEffect, useState } from "react";
// import modal from material UI
import { Modal, Box } from "@mui/material";
Remember to install @mui/material with
npm i @mui/material
Then let's declare a component with modal inside:
export default function Home() {
// state variable to decide if we should render pop-up
const [displayPopUp, setDisplayPopUp] = useState(true);
// when pop-up is closed this function triggers, we pass it to 'onClose' property of the modal
const closePopUp = () => {
// setting key "seenPopUp" with value true into localStorage
localStorage.setItem("seenPopUp", true);
// setting state to false to not display pop-up
setDisplayPopUp(false);
};
return (
<>
<div>
{/* conditional rendering, if displayPopUp is truthy we will show the modal */}
{displayPopUp && (
<Modal
open={true}
// once pop-up will close "closePopUp" function will be executed
onClose={closePopUp}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
>
<Box sx={style}>
{/* what user will see in the modal is defined below */}
<h1>Very important message</h1>
<h3>Just press OK button to never see it again</h3>
<button onClick={closePopUp}>OK</button>
</Box>
</Modal>
)}
</div>
{/* this is the main content of this page */}
<div>
<h1>The main content</h1>
</div>
</>
);
}
This will successfully render the page, display pop-up, close it when user clicks and save true
in the key seenPopUp
in the localStorage of a browser.
But now every time we refresh the page the pop-up will appear again although we've already seen it.
To solve this let's add the last step: useEffect
to check if we have seenPopUp
in localStorage:
// the useEffect to trigger on first render and check if in the localStorage we already have data about user seen and closed the pop-up
useEffect(() => {
// getting value of "seenPopUp" key from localStorage
let returningUser = localStorage.getItem("seenPopUp");
// if it's not there, for a new user, it will be null
// if it's there it will be boolean true
// setting the opposite to state, false for returning user, true for a new user
setDisplayPopUp(!returningUser);
}, []);
Now the final code for this entire component will look like this:
// import useEffect and useState
import { useEffect, useState } from "react";
// import modal from material UI
import { Modal, Box } from "@mui/material";
// write some style to pass into modal
const style = {
fontFamily: "Montserrat",
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
width: 300,
height: 200,
border: "10px solid hotpink",
boxShadow: 24,
padding: 5,
textAlign: "center",
background: "#de4899"
};
export default function Home() {
const [displayPopUp, setDisplayPopUp] = useState(true);
// when pop-up is closed this function triggers
const closePopUp = () => {
// setting key "seenPopUp" with value true into localStorage
localStorage.setItem("seenPopUp", true);
// setting state to false to not display pop-up
setDisplayPopUp(false);
};
// the useEffect to trigger on first render and check if in the localStorage we already have data about user seen and closed the pop-up
useEffect(() => {
// getting value of "seenPopUp" key from localStorage
let returningUser = localStorage.getItem("seenPopUp");
// if it's not there, for a new user, it will be null
// if it's there it will be boolean true
// setting the opposite to state, false for returning user, true for a new user
setDisplayPopUp(!returningUser);
}, []);
return (
<>
<div>
{/* conditional rendering, if displayPopUp is truthy we will show the modal */}
{displayPopUp && (
<Modal
open={true}
// once pop-up will close "closePopUp" function will be executed
onClose={closePopUp}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
>
{/* in the line below we pass our custom styles object to the modal via 'sx' prop*/}
<Box sx={style}>
{/* what user will see in the modal is defined below */}
<h1>Very important message</h1>
<h3>Just press OK button to never see it again</h3>
<button onClick={closePopUp}>OK</button>
</Box>
</Modal>
)}
</div>
{/* this is the main content of this page */}
<div>
<h1>The main content</h1>
</div>
</>
);
}
Et voilà!
Please remember, that localStorage belongs to a specific browser, so if a user open this page in Safari, they will not see pop-up next time they open the page in the same Safari. But if they will open the page in another browser, for example in Google Chrome, they will see the pop-up again.
Cheers!