Search code examples
javascriptreactjsreact-router

ReactJS Conditional Rendering: Component being rendered even though rendering conditions are not met


CONTEXT:

I only have this problem when I route directly to a modal route (putting the link in the url bar and pressing enter).

this.props.photoId is actually a this.props.routeParams.photoId that is passed into this component from the parent.


When the parent component mounts, it renders out its contents as expected. When a photo on this parent component is clicked,the app routes from myapp.com/parentContainer to myapp.com/parentContainer/:photoId. When this :photoId routeParam is present in the route, it is used to conditionally render a modal component. When a "close" button on the modal is clicked, the app routes back to myapp.com/parentContainer losing the :photoId routeParam, and thus closing the modal.

I am really at a loss. I have been using these patterns to render react components throughout my project without problems however I have a problem in this seemingly non-unique scenario:

...

render(){

  return(
    typeof this.props.photoId != 'undefined'
  ?
    <PhotoModal/>
  :
    null
  )
}

What I am noticing, is that even though this.props.photoId is undefined, it still renders <PhotoModal/>?

Again, When I route into the parent component and open the modal from the parent component the modal will close as expected, this problem only happens when I route directly to the modal route -when this happens the parent component renders, the modal renders as expected, but when I close the modal and lose the routeParam the modal does not close. This only happens when I route directly to the modal route from an external link / using the url bar. When I start in the parent component the conditional routeParam modal opening/closing functionality works 100% as expected.

I am receiving no errors or warnings, and I am able to see that the routeParam is in fact undefined, yet the component is not updating itself. I have no shouldComponentUpdate() clauses, so nothing should be preventing it especially since it is aware of the prop change.


Solution

  • This is, in fact, a very bizarre React/React Router bug that still exists in 2024. This will occur if you directly navigate to the URL of a child route (i.e. a route defined within another route's component). In this case, all conditionally rendered components of the child route will be rendered without regard to the condition that is defined.

    The workaround for this is to move the rendering condition inside the component of the child route:

    const PhotoModal = () => {
      //...all useState/useEffect/etc. goes here...
      if(someReasonNotToRender) { return (<></>); }
    
      // normal rendering logic here...
    }