user12560633
user12560633

Reputation:

CSS not changing when using React Router to route to another component

When I route my app to another component by using react-router-dom, the CSS doesn't change.

This is a minimalistic version of the code to demonstrate

App.js

import React from 'react';
import Home from './Home';

function App() {
    return (
      <div>
        <Home></Home>
      </div>
    );
}

export default App;

Home.js

import React from 'react';
import './Home.css';

const Home = () => {
    return (
        <h1>Home</h1>
    );
}

export default Home;

Home.css

body {
    background-color: blue;
}

Dashboard.js

import React from 'react'; import './Dashboard.css';

import React from 'react';
import './Dashboard.css';

const Dashboard = () => {
    return (
        <div className='content'>
            <h1>Dashboard</h1>
        </div>
    );
}

export default Dashboard;

Dashboard.css

.content {
    display: flex;
    align-content: center;
    align-items: center;
}

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import Dashboard from './Dashboard';
import * as serviceWorker from './serviceWorker';
import { BrowserRouter as Router, Route } from 'react-router-dom';

ReactDOM.render(
    <Router>
        <div>
        <Route exact path='/' component={App} />
        <Route path='/dashboard' component={Dashboard} />
        </div>
    </Router>, document.getElementById('root'));

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: ...
serviceWorker.unregister();

When I do /dashboard, it loads the Dashboard component, but it keeps the previous CSS that was loaded from the Home component that resides the App component. The background stays blue. I want that when I route to another component because I changed the URL, it loads whatever CSS that new component has attached to it and gets rid of whatever CSS was before. Is that possible?

Edit: I have made an example in CodeSandbox to illustrate. It's a little different from the code above due to the limitations of the playground, but the functionality is the same.

Edit frosty-cerf-s3dl3

From what can be seen, importing as a module ends up importing it globally. If we comment the line import Home from "./Home"; the blue background disappears. Just importing the component, imports the whole CSS despite the CSS being imported in a modular way. I'm not sure if I am missing something.

Edit 2:

Here are the different solutions I tried:

  1. CSS Modules, but the body style was still globally loaded.

  2. Styled components don't let me modify the body or html selectors CSS. They require me to create a <div> element and then have that element span the whole body which I would style as if it was the body. Which is a workaround I don't want to use because for that I rather use CSS Modules for the whole body spanning .

  3. Inline styling also doesn't let me modify the body or html selectors CSS. I would also need to use a workaround like a body spanning <div> as in Styled components.

Upvotes: 4

Views: 7197

Answers (3)

Suryansh Pundir
Suryansh Pundir

Reputation: 1

The problem I faced was that I used the same className for both components (Login and Register), copied the styles in css and made some changes which conflicted. When I set different classNames then it fixed the issue.

Upvotes: 0

user12560633
user12560633

Reputation:

After doing some more tests I have concluded that as of now it is not possible to change whatever CSS styles have been applied to a <body> or <html> selector in an React SPA when a CSS file is already loaded and one uses React Router to render other components. I still appreciate the answers and the time taken to help me find a solution. They are still valid answers if we are not talking about the <body> or <html> node in an HTML document. From them I learned about other ways to use CSS in React. I modified the original post with the solutions I tried.

What ended working was modifying the DOM styles with JavaScript whithin the component itself.

Home.js

import React from "react";

const Home = () => {
  // Modify the DOM Styles with JavaScript
  document.body.style.backgroundColor = "blue";

  // Or uncomment below to modify the
  // document root background color
  // which in this case would be <html>

  //document.bgColor = "blue";

  // Or modify the root tag style of the document instead of the
  // <body> (<html> in this case)

  //document.documentElement.setAttribute('style', 'background-color: green');

  return (
    <div>
      <h1>Home</h1>
      <form action="/dashboard">
        <input type="submit" value="Go to Dashboard" />
      </form>
    </div>
  );
};

export default Home;

Here is a working example:

Edit elastic-dawn-4stoi

Upvotes: 0

Fredrik
Fredrik

Reputation: 5108

The problem

When you import a css like you're doing here

import './Home.css';

you're importing it in a global scope, which means it will not disappear once imported.


The solutions

CSS Modules

What you want is either CSS Modules, which is used like this:

import styles from './Home.css';

<a className={styles.myStyleClass}>Hello</a>

Styled components

or a CSS-in-js framework such as styled components which is used like this:

import styled from 'styled-components';

const MyStyledElement = styled.a`
    color: blue;
`;

<MyStyledElement>Hello</MyStyledElement>

Regular objects / inline styling

or just "regular" CSS-in-js like:

const myStyle = {
    color: blue;
}

<a style={myStyle}>Hello</a>

There are plenty of options when it comes to styling, these alternatives are popular ones that I encourage you to explore and see which you enjoy.

Upvotes: 3

Related Questions