Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Component not re-rendering in React using a 'useEffect' hook

I'm creating a pop-up modal that should only appear on the user's first visit to a website. To do this, I'm using a useEffect hook to do two things: 1.) Check whether a cookie has already been set, (if it hasn't it will set the cookie) 2.) Based on that check, update the isCookie state to true/false.

I'm then passing the isCookie state value as a prop to the modal component, which will use the isCookie state to determine whether to show the modal.

Here's the issue: the modal is rendering based on the useState initial value only. Even after the state has been updated within useEffect, the modal does not re-render. I can confirm the state is updating via console logs, but I can't figure out how to get the modal to re-render.

The cookie check and placement within useEffect:

const [cookie, setCookie] = useState({isCookie:true})
    const newCookie = "visited=true; max-age=604800";

    useEffect(() => {
        if (!document.cookie.split(';').some((item) => item.trim().startsWith('visited='))) { //check to see if a cookie has been placed, if not this is a 'first visit'
            setCookie({isCookie:false});
            document.cookie = newCookie; //place cookie on first visit
        }
      }, [])



     <PopUp cookie={cookie.isCookie}/>

The relevant part of the pop-up/modal component:

const PopUp = (props) => {

/*if a cookie is present, the initial state of the modal is hidden, otherwise it's set to 'open' or shown*/

    const initialModalState = props.cookie ? {open: false} : {open: data.markdownRemark.frontmatter.show}

 const [modal, setModal] = useState(initialModalState)
    }
like image 243
Joel Avatar asked Jan 22 '26 23:01

Joel


1 Answers

useEffect does re-render the modal with a state change, but re-rendering will not reset the state variables for the component rendered inside it (that would be terrible if you think of a form with a controlled component.) Only remounting can do that.

Hence, when you set the modal to useState(intialModalState), it will always be dependent on the initial prop it receives and nothing else.

To sync the prop to state when re-rendering happens, you need a useEffect inside the child that listens to prop change:

const initialModalState = props.cookie ? {open: false} : {open: data.markdownRemark.frontmatter.show}

const [modal, setModal] = useState(initialModalState)

useEffect(() => {
  setModal(props.cookie ? {open: false} : {open: data.markdownRemark.frontmatter.show})
}, [props.cookie]);
like image 190
Agney Avatar answered Jan 25 '26 13:01

Agney



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!