Tips for dynamically changing the body class based on the page in a remix

I am trying to set parameters for the body class in root.jsx, which will change based on the page being viewed. I want to assign different values to the class in each route - for example, in _index it should be "company homepage", and in the restaurants route it should be "venue company", and so on. Is there a way to pass parameters from routes to root.jsx?

root.jsx


export default function App() {
  return (
    <html lang='en'>
      <head>
        <meta charSet='utf-8' />
        <meta name='viewport' content='width=device-width, initial-scale=1' />
        <link rel='preconnect' href='https://fonts.googleapis.com' />
        <link
          rel='preconnect'
          href='https://fonts.gstatic.com'
          crossOrigin='anonymous'
        />
        <link
          href='https://fonts.googleapis.com/css?family=Montserrat:wght@100,300,400,500,700&display=swap'
          rel='stylesheet'
        />
        <Meta />
        <Links />
      </head>
      <body>
        <Outlet />
        <ScrollRestoration />
        <Scripts />
        <LiveReload />
      </body>
    </html>
  );
}

_index.jsx


export default function Index() {
  const { startPage } = useLoaderData()
  const page = startPage.page.sections;
  return (
    <main id='main'>
      <PageComponents page={page} />
    </main>
  );
}

restaurants.jsx

export default function Restaurants() {
  const { restaurants } = useLoaderData();
  return (
    <>
      <PageComponents page={restaurants.sections} />
      <footer className='footer' />
    </>
  );
}

PageComponents.jsx

import loadable from "@loadable/component";

const components = {
  logo: loadable(() => import("./Logo")),
  intro: loadable(() => import("./Intro")),
  languageSwitch: loadable(() => import("./LanguageSwitch")),
  venueGroup: loadable(() => import("./VenueGroup")),
};

export default function PageComponents({ page }) {
  return (
    <main>
      {page
        .filter(({ type }) => !!components[type])
        .map(({ data, type }) => {
          const Component = components[type];

          return (
            <div key={type}>
              <Component data={data} />
            </div>
          );
        })}
    </main>
  );
}

Tried implementing a loader function in root.jsx to fetch API data for each page and include a variable for the body's className, but sometimes there may not be any data available about the pageClassName. In such cases, I need to manually pass the className parameter to each page from the routes and then transfer this parameter to root.jsx.

Answer №1

To streamline the process, you can create an object that maps CSS files to URL paths and utilize the useLocation hook to determine which child component is currently being displayed.

import { useLocation } from "@remix-run/react";

function SomeComponent() {
  const location = useLocation();
  // ...
}

Instead of modifying CSS directly from the parent component, it's recommended to assign different CSS files to individual components. Making changes to the parent's CSS file every time a child component renders can impact app performance and goes against React's optimization principles. If your website consists of distinct child pages under the same theme, maintaining consistency in the parent's layout elements like the Header and Footer across all pages aligns with good design practices.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Unlocking the secret to obtaining durable identity provider tokens for JavaScript in web browsers

Currently, I am working on implementing browser-side JavaScript code for login with Facebook, Amazon, Twitter, and Google using Cognito. I have reached a point where I am able to obtain client tokens for all four platforms. However, the issue is that thes ...

Ensuring a radio button is pre-selected by default in React by passing in a prop

Assume I have a React function similar to this function Stars({handleStarClick, starClicked}) { if (starClicked === 3) { document.getElementById('star3').checked = true } return ( <div className="rate"> ...

What is the best way to implement validation in a textarea to restrict the word count to a minimum of 250 and a maximum

I want to implement jQuery validation for a textarea field, with a requirement of 250 minimum words and 1000 maximum words. Additionally, I need to display the word count in a span tag next to the text area. How can I ensure that this validation works even ...

issue with retrieving data from PHP script via ajax

My attempts to use AJAX to call a PHP script have been unsuccessful. I added an echo alert statement in my deleteitem.php script to ensure it was being called, but no matter what I tried, it never executed. Both the PHP script and the JS script calling it ...

What impact does setting a variable equal to itself within a Dom Object have?

Within my code example, I encountered an issue with image sources and hrefs in a HTML String named tinymceToHTML. When downloading this html String, the paths were set incorrectly. The original image sources appeared as "/file/:id" in the String. However, ...

Having trouble setting up the next-auth login page and experiencing issues with the getProviders() function

Greetings to all fellow web developers, I am currently working on a Next.js application that utilizes next-auth for user authentication. I have set up the [...nextauth].js file in the "pages/api/auth" directory and a signin.js file in the "pages/auth/" di ...

SQL query for finding the number of shared nodes between two given nodes

How can we determine the common nodes between two specific nodes in SQL, using the following example: Count the occurrences of <li> tags between <h2 id="vgn">VGN A </h2> and <h2 id="vgn">VGN </h2>, as well as the total number ...

Centering "Label - Value" without tables in web design

It's common to have multiple labels (such as name, age, color) and a corresponding value for each one. One way to ensure that the values (for example Steve, 19, Red) all start in the same horizontal position is by organizing them in a 2 column, 3 row ...

I am facing an issue with the Tailwind Flowbite Datepicker dropdown UI when running "npm run prod" for minification. The class is not being added during minification on the npm

I have successfully integrated a Laravel project with Tailwind CSS. I have also implemented the Flowbite Datepicker using a CDN to include the necessary JavaScript. Initially, everything was working fine and the date-picker was displaying correctly. Howev ...

Unusual situation observed in ExpressJS: Callback function fails to execute

Currently, I am facing an issue with my web app built using expressjs and node. It seems that the functionality is not working correctly. An unusual situation has occurred where accessing the first link in the browser yields the expected results, while th ...

Incorporating map() with data passed down as props from App.js into child components

I have React version 18.2 and I want the child component in App.js to receive data and utilize the map() function. Although the child component successfully receives the data, it is encountering an issue when trying to use map(). An error message is disp ...

React - a search feature for array filtering

Lately, I've been delving into the intricacies of implementing a live search input that interacts with an array to create a file tree. Here is where you can find all the code: https://codesandbox.io/s/815p3k3vkj Although the solution seemed straightf ...

forming a boundary that stands alone, unattached to any other boundaries

I am trying to design a navigation bar that resembles the one depicted in the image provided. The concept involves creating a navigation bar where each border is separated from the others, potentially achieved using hr tags. However, I am struggling to fi ...

The progress indicator for AJAX file uploads is malfunctioning; the addEventListener('progress') method is not functioning as intended

For some reason, the event progress listener isn't firing in AJAX when using Chrome web browser. However, when simply using the form submit function to the form action, the file uploads as expected. Even though the file is uploading behind the scenes ...

Insert multiple hyperlinks into a text field on a separate webpage and store them individually in a MySQL database

Within my PHP file, I have an HTML form that includes a textbox where users can enter multiple links. For example: www.4shared.com/video/UryixZ7l/Puppy_loves_ringtones.htm www.4shared.com/video/UryixZ7l/Puppy_loves_ringtones.htm www.4shared.com/video/Ury ...

Exploring the angular js repeater component's context menu options

In one of my current projects, the client has specifically requested a right-click menu feature. However, the challenge lies in ensuring that the function triggered by the menu options has access to relevant information from the model. For instance, you ...

What is the best way to position my div outside of the wrapper while keeping the text inside?

For example: I want the blue text that says "join our discord server" to extend to 100% width when it's placed inside the wrapper. The reason it's inside the wrapper is to ensure the text matches up perfectly with the rest of the content. ...

What is the purpose of setting the image border to inline block?

When I added a span element as the circular border to my image, which is placed inside a span tag, I observed that the span tag was being pushed down. By giving the span a display:inline-block property, the issue was resolved. But why does this happen? ...

Modifying data within nested objects using Typescript

Imagine having an object like this: { b954WYBCC4YbsMM36trawb00xZ32: { activity1: "pending", activity2: "pending" }, ​ pby0CAqQ1hTlagIqBTQf6l2Ti9L2: { activity1: "pending", activity2: "pending" } } with the in ...

How can I use jQuery to vertically align an element?

Here's my website: Take a look here! I have a menu on the left column that I want to center. Take a look at the image below for a better understanding of what I'm trying to achieve. https://i.stack.imgur.com/ZzprT.png Here is the JavaScript c ...