Using getDerivedStateFromProps to fetch API data is causing the component to render many times

Non

I am trying to fetch some data from an API call. I am using getDerivedStateFromProps, componentDidMount,shouldComponentUpdateandcomponentDidUpdate`.

I am doing it like this because I need userToken which comes from userToken: store.signinScreen.userToken to be there before the call of the function GetPassengersData which needs userToken to get the data from the API.

This is the whole component:

// imports

class HomeScreen extends Component {
  static navigationOptions = {
    header: null,
  };

  state = {
    error: false,
  };

  static getDerivedStateFromProps(props, state) {
    if (props.userToken !== state.userToken) {
      return { userToken: props.userToken };
    }
    return null;
  }

  componentDidMount() {
    this.GetPassengersData();
  }

  shouldComponentUpdate(prevProps, state) {
    return this.props !== prevProps;
  }

  componentDidUpdate(prevProps, prevState) {
    const { error } = this.state;
    if (!error) {
      this.GetPassengersData();
    }
  }

  GetPassengersData = async () => {
    const { passengersDataActionHandler, userToken } = this.props;
    if (userToken && userToken !== null) {
      try {
        const response = await fetch(
          'http://myAPI/public/api/getPassengers',
          {
            method: 'POST',
            headers: {
              Authorization: `Bearer ${userToken}`,
              Accept: 'application/json',
              'Content-Type': 'application/json',
            },
          },
        );
        const responseJson = await response.json();
        if (has(responseJson, 'error')) {
          this.setState({ error: true });
          Alert.alert('Error', 'Please check your credentials.');
        } else {
          passengersDataActionHandler(responseJson.success.data);
        }
      } catch (error) {
        this.setState({ error: true });
        Alert.alert(
          'Error',
          'There was an error with your request, please try again later.',
        );
      }
    }
  };

  render() {
    return <TabView style={styles.container} />;
  }
}

HomeScreen.defaultProps = {
  userToken: null,
};

HomeScreen.propTypes = {
  navigation: PropTypes.shape({}).isRequired,
  passengersDataActionHandler: PropTypes.func.isRequired,
  userToken: PropTypes.oneOfType([PropTypes.string]),
};

export default compose(
  connect(
    store => ({
      userToken: store.signinScreen.userToken,
      passengersData: store.homeScreen.passengersData,
    }),
    dispatch => ({
      passengersDataActionHandler: token => {
        dispatch(passengersDataAction(token));
      },
    }),
  ),
)(HomeScreen);

With this implementation, the component renders many times so it breaks the application.

What could I be doing wrong?

Shubham Khatri

First of all you don't need to store userToken in state since you are not modifying it locally and hence you don't need getDerivedStateFromProps

Secondly, you need to trigger API call in componentDidUpdate only on as prop change and not directly without a check otherwise, the setState inside the API success or error will cause the component to re-render calling componentDidUpdate again and thus calling the API again resulting in a infinite loop

Third, the check inside shouldComponentUpdate comparing props is not exactly correct since nestedObjects props will give a false negative result and also if you write a deep equality check for props, the component won't re-render if the state changes.

// imports

class HomeScreen extends Component {
  static navigationOptions = {
    header: null,
  };

  state = {
    error: false,
  };

  componentDidMount() {
    this.GetPassengersData();
  }

  componentDidUpdate(prevProps, prevState) {
    if (prevProps.userToken !== this.props.userToken) {
      this.GetPassengersData();
    }
  }

  GetPassengersData = async () => {
    const { passengersDataActionHandler, userToken } = this.props;
    if (userToken && userToken !== null) {
      try {
        const response = await fetch(
          'http://myAPI/public/api/getPassengers',
          {
            method: 'POST',
            headers: {
              Authorization: `Bearer ${userToken}`,
              Accept: 'application/json',
              'Content-Type': 'application/json',
            },
          },
        );
        const responseJson = await response.json();
        if (has(responseJson, 'error')) {
          this.setState({ error: true });
          Alert.alert('Error', 'Please check your credentials.');
        } else {
          passengersDataActionHandler(responseJson.success.data);
        }
      } catch (error) {
        this.setState({ error: true });
        Alert.alert(
          'Error',
          'There was an error with your request, please try again later.',
        );
      }
    }
  };

  render() {
    return <TabView style={styles.container} />;
  }
}

HomeScreen.defaultProps = {
  userToken: null,
};

HomeScreen.propTypes = {
  navigation: PropTypes.shape({}).isRequired,
  passengersDataActionHandler: PropTypes.func.isRequired,
  userToken: PropTypes.oneOfType([PropTypes.string]),
};

export default compose(
  connect(
    store => ({
      userToken: store.signinScreen.userToken,
      passengersData: store.homeScreen.passengersData,
    }),
    dispatch => ({
      passengersDataActionHandler: token => {
        dispatch(passengersDataAction(token));
      },
    }),
  ),
)(HomeScreen);

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

How fetch data by api and render child component with it - react google maps

From Dev

Fetch data into React component and render it

From Dev

Not able to render React Component to many times

From Dev

Redux - Fetch data, but render in another component

From Dev

Render N times component based on the data in object

From Dev

React fetch api data to component

From Dev

Fetch Data from JSON File and render in custom JSX component using .map() method -Next JS

From Dev

Why is a Component method using fetch and settingState in response not causing a componentDidMount()?

From Dev

Making API Calls with React for fetch data and render it

From Dev

Using fetch to render json data in react app

From Dev

React+Javascript:-Component will update is getting called too many times causing my application to crash

From Dev

Fetching data from api before render component

From Dev

Not getting data using fetch Api

From Dev

How to fetch json data using vuejs component?

From Dev

using React useEffect to fetch data and controll component

From Dev

Reusable component data render using switch case

From Dev

How to fetch get data from API and render data in a table?

From Dev

Problem in render data after fetch the data from Api controller in Blazor

From Dev

How render a form many times

From Dev

Cannot fetch data from an API using componentDidMount: Can't call setState (or forceUpdate) on an unmounted component

From Dev

Render a react component n times

From Dev

Render react component multiple times

From Dev

Component render two times (reactJS)

From Dev

SetState dependent on API response is causing - Too many re-render error

From Dev

fetch data from API n times and then convert it into a single pandas dataframe

From Dev

How to fetch repeatedly and render updated api data in reactjs?

From Dev

Filtering Table data with useEffect Hook causing component to re-render infinitely

From Dev

How to fetch data asynchronously inside component and pass it as props to another component in render?

From Dev

React navbar component causing render to fail

Related Related

  1. 1

    How fetch data by api and render child component with it - react google maps

  2. 2

    Fetch data into React component and render it

  3. 3

    Not able to render React Component to many times

  4. 4

    Redux - Fetch data, but render in another component

  5. 5

    Render N times component based on the data in object

  6. 6

    React fetch api data to component

  7. 7

    Fetch Data from JSON File and render in custom JSX component using .map() method -Next JS

  8. 8

    Why is a Component method using fetch and settingState in response not causing a componentDidMount()?

  9. 9

    Making API Calls with React for fetch data and render it

  10. 10

    Using fetch to render json data in react app

  11. 11

    React+Javascript:-Component will update is getting called too many times causing my application to crash

  12. 12

    Fetching data from api before render component

  13. 13

    Not getting data using fetch Api

  14. 14

    How to fetch json data using vuejs component?

  15. 15

    using React useEffect to fetch data and controll component

  16. 16

    Reusable component data render using switch case

  17. 17

    How to fetch get data from API and render data in a table?

  18. 18

    Problem in render data after fetch the data from Api controller in Blazor

  19. 19

    How render a form many times

  20. 20

    Cannot fetch data from an API using componentDidMount: Can't call setState (or forceUpdate) on an unmounted component

  21. 21

    Render a react component n times

  22. 22

    Render react component multiple times

  23. 23

    Component render two times (reactJS)

  24. 24

    SetState dependent on API response is causing - Too many re-render error

  25. 25

    fetch data from API n times and then convert it into a single pandas dataframe

  26. 26

    How to fetch repeatedly and render updated api data in reactjs?

  27. 27

    Filtering Table data with useEffect Hook causing component to re-render infinitely

  28. 28

    How to fetch data asynchronously inside component and pass it as props to another component in render?

  29. 29

    React navbar component causing render to fail

HotTag

Archive