0

I just started teaching myself ReactJS a few weeks ago and I'm stuck trying to figure out why my API gets consistently hit in an infinite loop after selecting a value from a dropdown. I have a search component called StateSearch.js that is being rendered in the StatePolicyPage.js component.

In StatePolicyPage.js I call <StateSearch parentCallback={this.callbackFunction} /> so that I can get the value the user picked from the dropdown and set the state. In StateSearch.js I'm passing the selected value using props.parentCallback(response.data)

The problem is that an infinite loop occurs for some reason and my Rails API keeps getting called over and over instead of just returning the data one time.

(StateSearch.js) search component

import React, { useState } from 'react'
import Select from 'react-select'
import makeAnimated from 'react-select/animated';
import axios from 'axios';
import statesJSON from '../../helpers/states'; 

// uses 'react-select'
export default function StateSearch(props) {
  const [americanState, setAmericanState] = useState();

    // if a state was selected from the dropdown
    if (americanState) {
      axios.get("http://localhost:3001/get_stuff", {
        params: {
          state: americanState.value
        }
      }).then(response => {
        // the response back from the Rails server
        if (response.status === 200) {
          props.parentCallback(response.data); // send data back up to parent
        }
      }).catch(error => {
        console.log("Error fetching the state ", americanState.value, error);
      })
      event.preventDefault();
    }    

  // the dropdown select box for states.
  return (
    <div>
      <Select 
        options={statesJSON}
        placeholder="Select a State"
        onChange={setAmericanState}
        noOptionsMessage={() => 'Uh-oh nothing matches your search'}
        className=""
        components={makeAnimated()}
        isSearchable
        isClearable={true}
      />
    </div>
  )
}

(StatePolicyPage.js) the component that the search results should be passed to

import React, { Component } from 'react'
import Navigation from './Navigation';
import Container from 'react-bootstrap/Container';
import Row from 'react-bootstrap/Row';
import Col from 'react-bootstrap/Col';
import StateSearch from './search/StateSearch';

export default class StatePolicyPage extends Component {
  constructor(props) {
    super(props);

    this.state = { 
      id: '',
      stateName: '',
      updatedAt: '',
      createdAt: ''
    }    
  }

  callbackFunction = (childData) => {    
    console.log(childData);

    this.setState({
      id: childData.id,
      stateName: childData.state_name,
      updatedAt: childData.updated_at,
      createdAt: childData.created_at
    })
  }

  render() {
    return (
      <div>
        <Navigation 
          isLoggedIn={this.props.loggedInStatus} 
          user={this.props.user}
          handleLogoutClick={this.props.handleLogoutClick} 
          handleLogout={this.props.handleLogout} 
        />
        <Container>

         {/* get the dropdown value from the StateSearch back */}
          <StateSearch parentCallback={this.callbackFunction} /> 

          <div>
            <Row>   
            { this.state.id }
            </Row>   
          </div>
        </Container>
      </div>
    )
  }
}

2 Answers 2

2

Always use useEffect() hook for asynchronous tasks.

useEffect(() => {
// if a state was selected from the dropdown
    if (americanState) {
      axios.get("http://localhost:3001/get_stuff", {
        params: {
          state: americanState.value
        }
      }).then(response => {
        // the response back from the Rails server
        if (response.status === 200) {
          props.parentCallback(response.data); // send data back up to parent
        }
      }).catch(error => {
        console.log("Error fetching the state ", americanState.value, error);
      })
    }    
}, [americanState]);
Sign up to request clarification or add additional context in comments.

1 Comment

That worked! I just started learning ReactJS so I'm going to have to read up on useEffect. Thanks.
0

This line looks to me like it could cause an infinite loop:

 components={makeAnimated()}

I'm not entirely sure what this function is doing, but when passing functions to another component you can't directly invoke them.

Try replacing the above line with this:

components={makeAnimated}

or with this:

components={() => makeAnimated()}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.