Search code examples
reactjscomponentsrenderlifecycle-hook

React get new data in componentDidUpdate


I have a component which receives a list of news from two or three APIs. the first time the component renders, the apis are called and data is rendered in componentDidMount something like this:

componentDidMount() {
        this.state.platforms.forEach((platform, i) => {
            let objToSend = {
                phrase: this.props.searchParams.phrase,
                // this is the main place when input data changes
                ...this.props.searchParams.general_params,
                ...this.props.searchParams.platforms[i].api_params,
                stringPath: platform,
                apiPath: this.props.searchParams.platforms[i].apiPath,
            }
            this.props.loadData(objToSend)
            // this is the api call using redux which sends data as props to this component
 }

new when the phrase change, I want this component to re-render and re-run the componentDidMount, but it's not working because componentDidMount will run once. So I used componentDidUpdate, but as there are a number of calls so the api is being updated continuesly.

How can I make the component re-render and re-run componentDidMount every time I change the phrase


Solution

  • Here's one way to do something() when you re-render.

    import React, { Component } from 'react';
    import { render } from 'react-dom';
    
    const fakeFetch = (n) => {
      console.log(`Doing fake fetch: ${n}`)
      return n
    }
    
    class App extends Component {
      state = {
        value: false,
        number: 0,
      }
    
      componentDidMount() {
        const number = fakeFetch(this.state.number + 1);
        this.setState({ number })
      }
    
      componentDidUpdate(prevProps, prevState) {
        if (prevState.value !== this.state.value) {
          const number = fakeFetch(this.state.number + 1);
          this.setState({ number })
        }
      }
    
      toggle = () => {
        this.setState(({ value }) => ({ value: !value }))
      }
    
      render() {
        return (
          <React.Fragment>
            <h1>Number: {this.state.number}</h1>
            <button onClick={this.toggle}>re-render</button>
          </React.Fragment>
        );
      }
    }
    
    render(<App />, document.getElementById('root'));
    

    Live example here.