How to update a CSS Grid without re-rendering a specific component in ReactJS?

70
January 31, 2022, at 09:00 AM

I'm working on a React website with a video player that should continuously play on all routes. I'm trying to figure out a way to build a specific dynamic layout using CSS Grid that will update itself and the state of all components except the video component.

The main challenge is to make sure that the video component does not re-render in order to avoid any interruption in the playback.

The Homepage (initial) layout is the following:

// Code from an online generator
<div class="container">
  <div class="Video"></div>
  <div class="Content"></div>
  <div class="Sidebar"></div>
</div>
.container {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: 1fr 1fr 1fr;
  gap: 0px 0px;
  grid-auto-flow: row;
  grid-template-areas:
      "Video Video Sidebar"
      "Content Content Sidebar"
      ". . .";
  }
.Video { grid-area: Video; }
.Content { grid-area: Content; }
.Sidebar { grid-area: Sidebar; }

All other routes layout is the following:

// Code from an online generator
<div class="container">
    <div class="Content"></div>
    <div class="Video"></div>
    <div class="Sidebar"></div>
</div>
.container {  display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    grid-template-rows: 1fr 1fr 1fr;
    gap: 0px 0px;
    grid-auto-flow: row;
    grid-template-areas:
        "Content Content Video"
        "Content Content Sidebar"
        ". . .";
}
.Content { grid-area: Content; }
.Video { grid-area: Video; }
.Sidebar { grid-area: Sidebar; }

Is it possible to transition from Layout 1 to Layout 2 using CSS Grid without re-rendering the video component?

Answer 1

I managed to implement it by creating a layout with the video Component 1 outside of the Switch and passing the rest of the components as {children} of the layout.

I created two different grid-area CSS attribute versions for each component, for each layout, and used them to place the components in the grid cells according to the design.

Finally, I used useLocation() to get the current route and conditionally switch between the grid-area classes.

/* CSS */
.parent {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  grid-column-gap: 20px;
  grid-auto-rows: minmax(100px, auto) minmax(max-content, 2fr);
}
.video {
  grid-area: 1 / 1 / 9 / 10;
}
.sidebar {
  grid-area: 1 / 10 / 13 / 13;
}
.content {
  grid-area: 9 / 1 / 13 / 10;
}
.video-alt {
  grid-area: 1 / 10 / 1 / 13;
}
.sidebar-alt {
  grid-area: 2 / 10 / 13 / 13;
}
.content-alt {
  grid-area: 1 / 1 / 13 / 10;
}
// JSX
export const isHome = () => {
    let location = useLocation();
    return location.pathname === "/";
}
<div className="container mx-auto">
    <Header />
    <div className='parent'>
        <Stream />
        {isHome() ? <Chat /> : null}
        <div className={isHome() ? "content" : "content-alt"}  >
            {children}
        </div>
    </div>
    <Footer/>
</div>

// <Stream />
<div className={!isHome() ? "video-alt sticky top-20 z-40" : "video"}>
    <div ref={ref} className="">
        <VideoJS options={videoJsOptions} onReady={handlePlayerReady}/>
   </div>
   <div className="mt-4">{!isHome() ? <Chat /> : null}</div>
</div>
READ ALSO
Get user saved in session in EJB with NodeJS

Get user saved in session in EJB with NodeJS

Hi im having problem with express-session, it seems like not saving my user sessionHere is when I declare my session

71
Revslider jQuery &quot;Long-From-Top&quot; not working

Revslider jQuery "Long-From-Top" not working

i have a revslider and want to have a long-from-top but it still looks like a short-from-top

80
How can I check if the player is in a boat? [closed]

How can I check if the player is in a boat? [closed]

Want to improve this question? Update the question so it's on-topic for Stack Overflow

73
Clicking on non keyboard-focusable element with selenium chromedriver in python

Clicking on non keyboard-focusable element with selenium chromedriver in python

First I am trying to go to this link: driverget("https://www

80