Reputation: 43
When I am adding addData or updateData to the array of useEffect, it gets called infinite times,but i think it should only be called when button is clicked.
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
Upvotes: 1
Views: 5721
Reputation: 416
getData()
updates the state, due to the dispatch to redux state, which causes the state to change, which in turn will re-render your component. On re-render all the defined functions will be redefined, hence the functions will change.
useEffect()
will run everytime something in the dependency array changes, so it will run in an infinite loop due to the state changing and the functions being re-made every time the component re-renders.
You can use useCallback()
to fix it. useCallback()
will return any function defined inside it and will only redeclare the function when something in the useCallback()
dependency array changes.
You can try to do this with your code
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
Upvotes: 1
Reputation: 2890
useEffect(callback, dependencies) is the hook that manages the side-effects in functional components. The callback argument is a function to put the side-effect logic. dependencies is a list of dependencies of your side-effect: being props or state values.
useEffect(callback, dependencies) invokes the callback after initial mounting, and on later renderings, if any value inside dependencies has changed.
If you change one of the dependencies, the effect function will be executed. If you change a dependency in the effect function you will have an infinite loop.
Upvotes: 1