'React - Rerender a class component after the window pathname change

Greeting guys, I have an issue with a class component (that handle a list), the first time I mount the component works without any issue showcasing the expected values, unfortunately when I change the pathname while inside the class component it doesn't updated.

class Servicelist extends React.Component{
    constructor({path}) {
        super();
        this.path = {path}
        this.state = {
            services : [{
                title : 'Brand & Digital',
                description : `Lorem ipsum dolor sit amet conse ctetur adipiscing elit`,
                image : iservice1,
                details: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam.',
                cost: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam.',
                additional: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam.',
                link : '/services/brand_&_digital',
                id : 0
            },
            {
                title : 'Graphic Design',
                description : 'Lorem ipsum dolor sit amet conse ctetur adipiscing elit',
                image : iservice2,
                details: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam.',
                cost: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam.',
                additional: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam.',
                link : '/services/graphic_design',
                id : 1
            },
            {
                title : 'Advertising',
                description : 'Lorem ipsum dolor sit amet conse ctetur adipiscing elit',
                image : iservice3,
                details: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam.',
                cost: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam.',
                additional: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam.',
                link : '/services/advertising',
                id : 2
            },
            {
                title : 'Visual Identity',
                description : 'Lorem ipsum dolor sit amet conse ctetur adipiscing elit',
                image : iservice4,
                details: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam.',
                cost: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam.',
                additional: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam.',
                link : '/services/visual_identity',
                id : 3
            }]
        }
    }

    render() {
        console.log(this.path.path.pathname)
        const service = this.state.services.find(service => service.link === this.path.path.pathname)
        if (service) {
            return <Service {...service} />
        }
        else{
            return null
        }
      }
}

This component is been render directly into the app component where I have all my sections

function App() {
  const pathname = useLocation();

  return (
    <div className="App">
      <Nav/>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/services/:service" element={<Servicelist path={pathname}/>} />
        <Route path="/quote" element={<Quote />} />
      </Routes>
      <Footer/>
    </div>
  );
}

And the component <Servicelist /> its called by links inside the <Nav/> component like this...

<div className='burgernav-cont'>
            <div className='Home-link'>
                <Link to="/"> Home </Link>
            </div>
            <div className='services-links'>
                <Link to="/services/brand_&_digital"> Brand & Digital </Link>
                <Link to="/services/graphic_design"> Graphic Design </Link>
                <Link to="/services/advertising"> Advertising </Link>
                <Link to="/services/visual_identity"> Visual Identity </Link>
            </div>
            <div className='quote-link'>
                <Link to="/quote"> Quote </Link>
            </div>
            <div className='burguer'>
                <button onClick={() => setVisible(false)}><Bclose/></button>
            </div>
</div>


Solution 1:[1]

If you are using React-Router, You can use the useLocation look.

import { useLocation } from 'react-router-dom';

const { pathname } = useLocation();

Pass pathname through Props

<Component path={pathname}/>

Solution 2:[2]

You wanna make a raw router components by yourself? Ok, That's my:

  1. Use componentDidMount.
  2. Use ref.

Here are codes about kaboom.js that I used.


  state = {
    canvas: 'canvas',
  }

  componentDidMount() {
    kaboom({
      background: [134, 135, 247],
      width: 320,
      height: 240,
      scale: 2,
      canvas: this.refs.canvas as any,
    })
  }

  render() {
    return (
      <>
        <Card>
          {/* @ts-ignore */}
          <canvas width="640" height="640" ref={this.state.canvas}></canvas>
        </Card>
      </>
    )
  }

I decide to give you a test codes:

class Test extends Component {
    state = {
        path: 'path',
    }

    lazyRoute = (Component: any) => {
        return (props: any) => <Component {...props} />
      }

    componentDidMount() {
        const service = this.state.services.find(service => service.link === window.location.pathname)


        if (service) {
            
            ReactDom.render(lazyRoute(Service), this.refs.path) 
        }else {
            
            ReactDom.render(<NotFound />, this.refs.path) 
        }
    }

    render() {
        <div ref={this.state.path}></div>
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 IQ Digit
Solution 2 wenxuan feng