Search code examples
ruby-on-railsreactjsaxiosreact-hooksreact-on-rails

Why is my axios get call repeating over and over using React.useEffect?


I am using axios on a React w/ Hooks front end to make a get request to populate my react-google-maps/api GoogleMaps Marker components using seed data in my rails backend. When I let the rails server run, the server repeatedly makes this call.

The following line causes the axios.get to be called on a loop:

 React.useEffect(() => {
        // Get Coordinates from api
        // Update Coordinates in state
        axios.get('/api/v1/coordinates.json')
        .then(response => response.data.data.map(coord => 
              setCoordinateFromApi(coord.attributes)))
        .catch(error => console.log(error))
    }, [coordinates.length]) 

This successfully populates the map but means I can't use onClick's functionality (because I presume the stack is being topped with this request?)

My index method on my CoordinatesController in Rails:

def index
  coordinates = Coordinate.all
  render json: CoordinateSerializer.new(coordinates).serialized_json
end

NB: this is my first project linking React to Rails as well as using Hooks


Solution

  • I would assume that you have this useState defined above:

    const [coordinated, setCoordinatesFromApi] = useState([])
    

    If it is, then this is the root cause:

    React.useEffect(() => {
      axios.get(...).then(coordinates => setCoordinateFromApi(coord.attributes))
    }, [coordinates.length])
    

    By doing so, you ask React.useEffect to always call axios.get whenever coordinates.length change. Which will make this useEffect an infinite loop (because you always change the coordinates value whenever the axios request finish).

    If you only want to execute it once, you should just pass an empty array on the useEffect, like this

    React.useEffect(() => {
      axios.get(...).then(coordinates => setCoordinateFromApi(coord.attributes))
    }, [])
    

    That way, your axios.get will only be called once and you will no longer have infinite loop