score:4

If I were you I would fetch from my api outside of the route components and just pass it down to the route. Then you don't have to worry about the route change and any programming that would be involved in manipulating the default behavior of the router. You can do this one of two ways.

First Do your api call higher in the component tree. So if you would do your api call in the app component then pass it down to the Route you wouldn't have to worry about the rendering of the route. Your logic would be outside of it.

Second If you don't want a messy app component you could create a context component and do your logic in there. Then just wrap your components in your context component that you created. Like so:

Here is a codesandbox Sandbox

Your app component

import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter, Route, Link, Switch } from "react-router-dom";

import First from "./First";
import Second from "./Second";
import Context from "./Context";
import "./styles.css";

function App() {
  return (
    <BrowserRouter>
      <div className="App">
        <h1>Router Rerendering Fix</h1>
        <ul>
          <li>
            <Link to="/">First Route</Link>
          </li>
          <li>
            <Link to="/second">Second Route</Link>
          </li>
        </ul>
        <Switch>
          <Context>
            <Route exact path="/" component={First} />
            <Route path="/second" component={Second} />
          </Context>
        </Switch>
      </div>
    </BrowserRouter>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Your articles component

import React, { useContext } from "react";
import {ApiContext} from "./Context";

const First = () => {
  const context = useContext(ApiContext);
  return (
    <div>
      <div>First Route</div>
      <ul>
        {context.map((article, index) => (
          <li key={index}>{article}</li>
        ))}
      </ul>
    </div>
  );
};

export default First;

Your context component

import React, {useState, useEffect} from 'react';

export const ApiContext = React.createContext();

const Context = props => {
  const [articles, setArticles] = useState([]);

  useEffect(() => {
    console.log('rendered');
    setArticles(['Article One', 'Article Two', '...ect'])
  }, []);

  return (
    <ApiContext.Provider value={articles}>
      {props.children}
    </ApiContext.Provider>
  )
}

export default Context;

Related Query

More Query from same tag