0

Good morning everyone,

I just finished my training in React and I wanted to make a project to practice. To start, i'm juste posting data in a firebase database. Then, i would like to fetch data to display it in a react component using hooks (useState and useEffect).

The problem is i end up in the classic trap of infinite loop after fetching datas with axios, but i can't figure out how to stop it with dependency.

Please find code below :

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

import classes from './Incomes.module.css'
import axios from '../../../axios'

import Button from '../../UI/Button/Button'
import Input from '../../UI/Input/Input'

const Incomes = (props) => {

const [inputValue, setInputValue] = useState('');
const [fetchedTypes, setFetchedTypes] = useState([]);

const onClickHandler = () => {
    const type = {type: inputValue}
    axios.post('/types.json', type)
    .then(response => {
        alert('ok c good');
    })
    .catch(error => console.log(error))
}

const onChangeHandler = (event) => {
    setInputValue(event.target.value)
}

useEffect(() => {
    axios.get('/types.json')
    .then(response => {
        let types = []
        for(let key in response.data) {
            types.push({...response.data[key], id: key})
        }
        console.log('types : ', types)
        setFetchedTypes(prevFetchedTypes => [...prevFetchedTypes, types])
    })
    .catch(error => console.log(error))
    console.log('fetchedtypes', fetchedTypes)
}, [fetchedTypes])

    return (
        <div className={classes.Incomes}>
            <h2>Paramètres des entrées</h2>
            <h3>Ajouter un type de revenu</h3>
            <Input type="text" disabled={false} change={onChangeHandler} placeholder="Nom du champ"></Input>
            <Button onClick={onClickHandler} type="Normal" clicked={onClickHandler}>Ajouter</Button>
            <h3>Liste des types de revenus disponibles</h3>
        </div>
    )
}

export default Incomes;

When i console log types, the datas are correct. But when i console log fetchedTypes, it's an empty array.

I found this post but it's not working neither : React useEffect infinite loop fetch data axios

I'm not sure if it's an issue with the way I use useEffect or the way I update state, or both.

Thank you for your help

Have a good day

Mikev60
  • 103
  • 1
  • 8

1 Answers1

0

The reason you're getting an infinite loop is because of your useEffect and for two reasons.

  • I'm assuming fetchedTypes is not a primitive but some object/array so it'll always be different every time. Don't use it with useEffect. If you want to depend on objects, go for useDeepCompareEffect by Kent but you don't need it here.
  • The second and main reason for your infinite loop is the statement:
    setFetchedTypes(prevFetchedTypes => [...prevFetchedTypes, types])

Your useEffect is updating fetchedTypes with the above line but it's also meant to run when fetchedTypes changes. So useEffect updates it and since it's a dependency which has changed, useEffect runs again resulting to an infinite loop.

A possible solution: If you want to fetch data when your component loads, change your useEffect to this:

useEffect(() => {
    axios.get('/types.json')
    .then(response => {
        let types = []
        for(let key in response.data) {
            types.push({...response.data[key], id: key})
        }
        console.log('types : ', types)
        setFetchedTypes(types)
    })
    .catch(error => console.log(error))
    console.log('fetchedtypes', fetchedTypes)
}, [])
  • Ignore any lint warning. An empty dependency array means this will run only once when the component renders.

But since you have an on click handler, I'm assuming you want to update the data after the POST request. If your onClickHandler returns the newly created type then do this:

const onClickHandler = () => {
    const type = {type: inputValue}
    axios.post('/types.json', type)
    .then(response => {
        const newType = response.data;
        const updatedTypes = [...types, newType]
        setFetchedTypes(updatedTypes)
    })
    .catch(error => console.log(error))
}

NOTE: I don't know the structure of your types so I'm working with assumptions but that's the idea

kimobrian254
  • 557
  • 3
  • 10
  • Thank you, it's working. Actually, when i consoled log after the use effect, the datas were correct, i am trying to figure why (the cycle of set in hooks)... – Mikev60 Oct 16 '20 at 10:58