Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to render same component with different props inside react-router <Route>?

I have a News component which takes some props, and I want to make it re-render whenever I click on <Link /> with the corresponding category props. It updates the URL but does not re-render the component.

<Routes>
  <Route
    path="/"
    element={
      <News
        country={this.country}
        apiKey={this.API_KEY}
        pageSize={this.pageSize}
        category="general"
      />
    }
  />
  <Route
    path="/business"
    element={
      <News
        country={this.country}
        apiKey={this.API_KEY}
        pageSize={this.pageSize}
        category="business"
      />
    }
  />
  <Route
    path="/entertainment"
    element={
      <News
        country={this.country}
        apiKey={this.API_KEY}
        pageSize={this.pageSize}
        category="business"
      />
    }
  />
</Routes>

These are my <NavLink />

<li className="nav-item">
  <NavLink className="nav-link" aria-current="page" to="/">
    Home
  </NavLink>
</li>
{this.props.categories.map((category) => {
  return (
    <li key={category} className="nav-item">
      <NavLink to={`/${category}`} className="nav-link">
        {category[0].toUpperCase() +
          category.slice(1, category.length)}
      </NavLink>
    </li>
  );
})}
like image 723
iamWinn1 Avatar asked Jul 03 '26 09:07

iamWinn1


1 Answers

react-router/react-router-dom optimizes rendering by keeping the same component instance mounted even though it is rendered on multiple routes. This is a performance optimization to save unmounting and remounting the same component only to pass it different props values. In other words, the component remains mounted even though the route changed, and should handle the props value updating in the componentDidUpdate lifecycle method or useEffect hook with dependency.

Based on the routes and the passed props it's really that this News component has some dependency on the category prop as that's the only prop I see that is different.

The News component should likely have a useEffect hook with a dependency on this category prop to run/load whatever data is different based on this different prop value.

Example:

const News = ({ apiKey, category, country, pageSize }) => {
  useEffect(() => {
    // a dependency value changed, rerun some logic
  }, [apiKey, category, country, pageSize]);

  ...
};

If News is a React class-based component then it should implement the componentDidUpdate method.

class News extends React.Component {
  ...

  componentDidUpdate(prevProps) {
    const { apiKey, category, country, pageSize } = this.props;

    if (
      category !== prevProps.category
      /* || other props change conditions */ 
    ) {
      // a dependency value changed, rerun some logic
    }
  }

  ...
};

Also, based on this, since it also appears that the category and the URL path match, for the most part, you could likely also make the code more dry by rendering a single route with the category as a route path parameter, and applying the same useEffect hook logic to rerun the logic that depends on the category value.

Example:

<Routes>
  <Route
    path="/:category?"
    element={
      <News
        country={this.country}
        apiKey={this.API_KEY}
        pageSize={this.pageSize}
      />
    }
  />
</Routes>
import { useParams } from 'react-router-dom';

const News = ({ apiKey, country, pageSize }) => {
  const { category = "general" } = useParams();

  useEffect(() => {
    // a dependency value changed, rerun some logic
  }, [apiKey, category, country, pageSize]);

  ...
};

Again, if News is a Class-component, then use the appropriate componentDidUpdate lifecycle method and implement a custom withRouter Higher Order Component in order to inject the category route path parameter as a prop.

Using a React key on the News component should only be used as a last resort since it invloves actually tearing down, e.g. unmounting, and remounting the component which is a lot more work than simply rerendering the component with updated prop values.

like image 158
Drew Reese Avatar answered Jul 04 '26 22:07

Drew Reese



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!