简体   繁体   中英

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)
    }

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]);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM