提取数据后,为什么我的状态没有更新?

时间:2020-10-16 10:12:20

标签: reactjs axios react-hooks use-effect

大家早上好

我刚完成React的培训,我想做一个练习项目。 首先,我只是在Firebase数据库中发布数据。 然后,我想获取数据以使用钩子(useState和useEffect)将其显示在react组件中。

问题是我用axios提取数据后最终陷入了经典的无限循环陷阱,但是我不知道如何通过依赖关系来停止它。

请在下面找到代码:

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;

当我使用控制台日志类型时,数据是正确的。 但是,当我使用控制台日志fetchedTypes时,它是一个空数组。

我找到了这篇文章,但是它都不起作用: React useEffect infinite loop fetch data axios

我不确定这是我使用useEffect的方式还是更新状态的方式,还是两者都有问题。

感谢您的帮助

祝你有美好的一天

1 个答案:

答案 0 :(得分:0)

出现无限循环的原因是由于useEffect和两个原因。

  • 我假设fetchedTypes不是原始元素,而是某些对象/数组,因此每次总是不同。不要将它与useEffect一起使用。如果您想依赖对象,请肯特(Kent)推荐useDeepCompareEffect,但这里不需要。
  • 无限循环的第二个主要原因是:
    setFetchedTypes(prevFetchedTypes => [...prevFetchedTypes, types])

您的useEffect将使用上面的行更新fetchedTypes,但它也应在fetchedTypes更改时运行。因此useEffect对其进行了更新,并且由于它的依赖项已更改,因此useEffect再次运行会导致无限循环。

可能的解决方案: 如果要在加载组件时获取数据,请将useEffect更改为此:

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)
}, [])
  • 忽略任何棉绒警告。空的依赖项数组意味着此组件将仅在组件渲染时运行一次。

但是,由于您具有点击处理程序,因此我假设您要在POST请求后更新数据。如果您的onClickHandler返回了新创建的类型,请执行以下操作:

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))
}

注意: 我不知道您的类型的结构,因此我正在做一些假设,但这是个主意