How to change background based on page url react js?

Viewed 1051

I have a simple app with a few pages, now I would like to change the background color based on page URL using react js,

What is expected?:

When a pathname is /movies I want to change the background to red

Here is what I have so far

 import React from 'react'

function Testing() {
const[moviesUrlBackgroundColor, setMoviesUrlBackgroundColor] = useState('green');


const getMoviesUrl = window.location.pathname;


if(getMoviesUrl == '/movies'){
    setMoviesUrlBackgroundColor('red');
}else{
    setMoviesUrlBackgroundColor('green');
}

    return (
        <div>
            <Container style={{backgroundColor:moviesUrlBackgroundColor}}>
            
                Testing
            </Container>
        </div>
    )
}

export default Testing

const Container = styled.div`
    background-color:green
`;

Unfortunately, I am getting the following URL

app.js:38323 Uncaught Invariant Violation: Too many re-renders. React limits the number of renders to prevent an infinite loop.

What do I need to do this working?

5 Answers

You should have an extra check to make sure you have set background color or not.Your current code is causing rerender infinte times

 import React from 'react'

 function Testing() {
 const[moviesUrlBackgroundColor, setMoviesUrlBackgroundColor] = useState('green');
 const [bgFlag, setbgFlag] = useState(false);


 const getMoviesUrl = window.location.pathname;

 if(!bgFlag){
     setMoviesUrlBackgroundColor(getMoviesUrl == '/movies' ? 'red' : 'green')
     setbgFlag(true)
 }

return (
    <div>
        <Container style={{backgroundColor:moviesUrlBackgroundColor}}>
        
            Testing
        </Container>
    </div>
)
 }

 export default Testing

const Container = styled.div`
    background-color:green
`;

Use an useEffect block so you can perform side-effects effectively.

  useEffect(() => {
    if(getMoviesUrl === '/movies'){
      console.log("running")
        setMoviesUrlBackgroundColor('red');
    }else{
        setMoviesUrlBackgroundColor('green');
    }
  },[getMoviesUrl]);

The problem is that you call setMoviesUrlBackgroundColor without wrapping in an effect which results in getting called recursively.

In order to fix this, you just simple set state as needed in this case is your pathname has been changed:

React.useEffect(() => {
  if (getMoviesUrl == '/movies'){
    setMoviesUrlBackgroundColor('red');
  } else{
      setMoviesUrlBackgroundColor('green');
  }
}, [getMoviesUrl])

Ok, I think I got it, you're creating an infinite loop on your first if statement:

if (getMoviesUrl == '/movies') {
    // every time you change state, that causes your component
    // to re-render, and when it re-renders again you're checking
    // changing your state AGAIN, so it's an infinite loop
    setMoviesUrlBackgroundColor('red');
}

I'll would recommend using react-route for this and getting the url from params, and then update the background color on componentDidMount or useEffect hook when component mounts for the first time, to prevent infinite loops.

Window.location.pathname was resetting state each render, so it needs to be placed within the useEffect hook to prevent re-renders.

Also, this would be a good use-case to pass props to your styled component. Also included this in the code below.

Here's a link to a codesandbox I made with the solution. https://codesandbox.io/s/musing-mirzakhani-njmsh?file=/src/random.js:0-620

import React, { useState, useEffect } from "react";
import styled from "styled-components";

const Container = styled.div`
  background: ${(props) => props.backgroundColor || "green"};
`;

const Testing = () => {
  const [moviesUrlBackgroundColor, setMoviesUrlBackgroundColor] = useState(
    "green"
  );

  useEffect(() => {
    const getMoviesUrl = window.location.pathname;
    if (getMoviesUrl === "/movies") {
      setMoviesUrlBackgroundColor("yellow");
    }
  }, [moviesUrlBackgroundColor]);

  return (
    <div>
      <Container backgroundColor={moviesUrlBackgroundColor}>Test</Container>
    </div>
  );
};

export default Testing;

Cheers!

Related