lane
lane

Reputation: 679

React useState causes render loop

I am fetching data and trying to store the response in state using the useState hook. When I set selectedRouteDirection from the getRouteDirection function, render runs on an infinite loop. How can I set the state with useState and render only once?

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

const parser = require('xml-js');

const RouteSelect = props => {
    const { routes } = props;

    const [selectedRouteName, setRouteName] = useState('');
    const [selectedRouteDirection, setRouteDirection] = useState('');

    useEffect(() => {
        if(selectedRouteName) {
            getRouteDirection();
        }
    });

    const onChangeHandler = event => {
        setRouteName({ name: event.target.value });
    }

    const getRouteDirection = () => {

        const filteredRoute = routes.filter(route => route.Description._text === selectedRouteName.name);
        const num = filteredRoute[0].Route._text;

        let directions = [];
        fetch(`https://svc.metrotransit.org/NexTrip/Directions/${num}`)
            .then(response => { 
                return response.text();
            }).then(response => {
                return JSON.parse(parser.xml2json(response, {compact: true, spaces: 4}));
            }).then(response => { // offending block
                directions = response.ArrayOfTextValuePair.TextValuePair;
                // console.log(directions);
                setRouteDirection(directions);    
            })
            .catch(error => {
                console.log(error);
            });

        console.log(selectedRouteDirection);
    }

    const routeOptions = routes.map(route => <option key={route.Route._text}>{route.Description._text}</option>);

    return (
        <Fragment>
            <select onChange={onChangeHandler}>
                {routeOptions}
            </select>
        {selectedRouteName ? getRouteDirection() : null} 
        </Fragment>
    );
};

export default RouteSelect;

Upvotes: 0

Views: 1363

Answers (1)

Ali Faris
Ali Faris

Reputation: 18592

that because you're calling getRouteDirection() in the returned value , instead use useEffect to call getRouteDirection()

 ...

 useEffect(() => getRouteDirection());

 return (
        <Fragment>
            <select onChange={onChangeHandler}>
                {routeOptions}
            </select>
         //some thing 
        </Fragment>
    );

explanation: getRouteDirection() will change the state every time it's called and when the state changed this will result in calling getRouteDirection() again, and so on.

Upvotes: 1

Related Questions