1

I have a class Dashboard component which fetch data from multiple API's in componentDidMount() with props received from route and renders a charts.

    componentDidMount() {
        this.urls = ChartProps[this.chart].api;
        this.title = ChartProps[this.chart].titles;
        
        Promise.all(
                    urls.map(url =>
                    fetch(url)
                    .then((res) => res.json())
                    .catch(error => console.log('There was a problem!', error))
                ))
                .then((json) => {
                    this.formatJsonForChart(json);
                });
        
    }

Now there are different props from different routes get received on same component.

    <BrowserRouter>
        <Navlist/>
        <Routes>
            <Route path="/" element={<Dashboard element={<Dashboard chart='chart1'/>} />} />
            <Route path="/chart2" element={<Dashboard chart='chart2'/>} />
            <Route path="/chart3" element={<Dashboard chart='chart3'/>} />
            <Route path="/chart4" element={<Dashboard element={<Dashboard chart='chart4'/>} />} />
            <Route path="*" element={<ErrorPage />} err='404' />
        </Routes>
    </BrowserRouter>

All the API's that fetches a data are based on received props. The problem here is function that renders a chart get called in componentDidMount() so it works fine on first route click. But when clicked on other route it doesn't call componentDidMount() since component is already mounted so charts doesn't get updated get clicked on other route.

What alternate approach can be taken?

Amila Senadheera
  • 12,229
  • 15
  • 27
  • 43
Mahendra
  • 908
  • 1
  • 18
  • 38
  • 1
    Yes because `componentDidMount` will be called just on first render. Have you tried to use `componentDidUpdate`? Take a look at https://dev.to/cesareferrari/how-to-use-componentdidupdate-in-react-30en – Giovanni Esposito Jan 21 '22 at 14:36
  • 1
    I dint try it. But was with no state check condition. It worked.. – Mahendra Jan 21 '22 at 15:13
  • Well I'm happy that is working BUT remember that this function will be called an huge amount of time and in several prjoect I had was the root cause of performance issues... So use it but with a lot of care =) – Giovanni Esposito Jan 21 '22 at 15:17
  • Thanks @GiovanniEsposito , any better alternative? – Mahendra Jan 21 '22 at 15:26
  • No problem. No I have no other alternatives because I think `componentDidMount` is the correct way but must be programmed in a smart way (for example, componentDidMount complete signature is `componentDidUpdate(prevProps, prevState, snapshot)` so you could check if prevProps are different from current props and only in this case call the fetch, in this case you avoid to call the fetch every time component will be updated). – Giovanni Esposito Jan 21 '22 at 15:37

1 Answers1

0

You could abstract the logic in your componentDidMount lifecycle method into a function that is called in both componentDidMount and componentDidUpdate lifecycle methods.

OR

Provide a unique React key to each Dashboard component so when the route changes React will unmount/remount a new instance.

<BrowserRouter>
  <Navlist/>
  <Routes>
    <Route
      path="/"
      element={<Dashboard key="/chart1" chart='chart1'/>}
    />
    <Route
      path="/chart2"
      element={<Dashboard key="/chart2" chart='chart2'/>}
    />
    <Route
      path="/chart3"
      element={<Dashboard key="/chart3" chart='chart3'/>}
    />
    <Route
      path="/chart4"
      element={<Dashboard key="/chart4" chart='chart4'/>}
    />
    <Route path="*" element={<ErrorPage />} err='404' />
  </Routes>
</BrowserRouter>
Drew Reese
  • 165,259
  • 14
  • 153
  • 181