useEffect 被多次调用

时间:2021-02-13 12:44:34

标签: reactjs react-redux

当我将 addData 或 updateData 添加到 useEffect 数组时,它被无限次调用,但我认为它应该只在单击按钮时调用。

import axios from 'axios'
import { Button, TextField } from '@material-ui/core'
import React,{useState,useEffect} from 'react'
import { useDispatch, useSelector } from 'react-redux'
import Applebar from './MainPage/Applebar'
import './style.css'
import { add } from '../reducers/data/dataReducer'
import Loader from './Loader/Loader'
const Main = () => {
    const user=useSelector(state => state.auth);
    const dispatch=useDispatch()
    const [data,setData]=useState({
        site:"",
        uname:"",
        password:""
    })
    const handleChange=(e)=>{
        setData({...data, [e.target.name]:e.target.value})
    }
    
    const addData=async(e)=>{
        console.log('add fun  called')
        e.preventDefault()
        await axios.post('http://localhost:5000/data', data,{
            withCredentials: true 
         });
    }
    

    const userData=useSelector(state=>state.data)
    const arrData=userData.data
    const deleteData=async(id)=>{
        await axios.put("http://localhost:5000/data",{id},{
            withCredentials: true 
         })
    }

    const editData=(id)=>{
        const {data}=userData
        const reqdData=data.filter((d)=>{return (d._id==id)})
        const [getData]=reqdData
        setData(
        {
            site:getData.site,
            uname:getData.uname,
            password:getData.password
        })
        setCurrentId(id)
    }
    const [currentId,setCurrentId]=useState(null)
    const updateData=async()=>{
        if(currentId!==null)
            console.log(currentId)
            const updateData=await axios.put("http://localhost:5000/update",{...data,_id:currentId},{
                withCredentials: true 
             })
            console.log(updateData)
    }

    const getData=async()=>{
        const data=await axios.get('http://localhost:5000/data',{
            withCredentials: true 
         }).then((response)=>{
                dispatch(add(response.data))
            })    
        }

    useEffect(()=>{
        console.log("useeffect called")
        getData()
        
    },[dispatch])//, addData, updateData oncalling these function infinite calling
    
        return (
            <div>
                <Applebar />
                <h1>{user?.currentUser?.name}</h1>
                <div className="main_body">
                    <div className="main_form">
                            <form>
                                <div className="form_field">
                                    <TextField
                                    id="outlined-basic"
                                    name="site"
                                    label="site"
                                    variant="outlined"
                                    value={data.site}
                                    onChange={handleChange}/>
                                </div>
                                <div className="form_field">
                                    <TextField
                                     id="outlined-basic"
                                     name="uname"
                                     label="uname"
                                     variant="outlined"
                                     value={data.uname}
                                     onChange={handleChange}/>
                                </div>
                                <div className="form_field">
                                    <TextField
                                     id="outlined-basic" 
                                     name="password" 
                                     label="password" 
                                     variant="outlined" 
                                     value={data.password} 
                                     onChange={handleChange}/>
                                </div>
                                <div className="form_field">
                                    <Button onClick={addData} color="primary" variant="contained" >Add</Button></div>
                                <div className="form_field">
                                    <Button onClick={updateData} color="primary" variant="contained" >Update</Button></div>
                            </form>
                    </div>
                    <div className="main_data">
                        {arrData?.map((data)=>{
                                
                                return(
                                    <div key={data._id}>
                                        {data.site}
                                        <button onClick={()=>{deleteData(data._id)}}>-</button>
                                        <button onClick={()=>{editData(data._id)}}>editData</button>
                                    </div>
                                )
                        })}
                    </div>
                </div>
            </div>
        )
    }
//}

export default Main

2 个答案:

答案 0 :(得分:1)

useEffect(callback, dependencies) 是管理功能组件中副作用的钩子。回调参数是一个放置副作用逻辑的函数。依赖项是你的副作用的依赖项列表:道具或状态值。

useEffect(callback, dependencies) 在初始安装后调用回调,并且在以后的渲染中,如果依赖项中的任何值发生了变化。

如果改变其中一个依赖项,效果函数就会被执行。 如果您更改效果函数中的依赖项,您将陷入无限循环。

答案 1 :(得分:1)

getData() 更新状态,由于分派到 redux 状态,这会导致状态更改,进而重新渲染您的组件。重新渲染时,所有定义的函数都会被重新定义,因此函数会发生变化。

useEffect() 将在依赖项数组中的每次更改时运行,因此由于每次组件重新渲染时状态更改和重新制作的功能,它将在无限循环中运行。

您可以使用 useCallback() 来修复它。 useCallback() 将返回其中定义的任何函数,并且只会在 useCallback() 依赖项数组中的某些内容发生更改时重新声明该函数。

你可以尝试用你的代码来做到这一点

import {useCallback} from 'react'

    const addData= useCallback(async(e)=>{
        console.log('add fun  called')
        e.preventDefault()
        await axios.post('http://localhost:5000/data', data,{
            withCredentials: true 
         });
    }, [])

 const updateData=useCallback(async()=>{
        if(currentId!==null)
            console.log(currentId)
            const updateData=await axios.put("http://localhost:5000/update",{...data,_id:currentId},{
                withCredentials: true 
             })
            console.log(updateData)
    }, [])

    useEffect(()=>{
        console.log("useeffect called")
        getData()
        
    },[dispatch]) // now you can put those dependencies in this array,
// even though you only need to add getData. You don't even need dispatch here