当我将 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
答案 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