'React I have an endless loop rendering my edit component
I have two components. My dashbord-component, in which I am dispatching the getAllDropDownRessort, which triggers the findAll function in my dropdownRessortSlice and an edit-component, in which I am dispatching the getDropdownRessort, which triggers the findOne function in the same slice. When I calling the edit-component, it not ends rendering, and the redux-devtools tell me that it always renders the findAll function. Thanks for your help.
Here is my dashbord-component:
const DropdownRessorts = () => {
//bring in
const {dropdownRessort, isLoading, isError, message} = useSelector((state)=>state.dropdownRessort);
const dispatch = useDispatch();
useEffect(()=>{
if(isError){
console.log(message);
}
dispatch(getAllDropdownRessort());
return ()=>{
dispatch(reset());
}
}, [dispatch, isError, message]);
//bring out
const [formdata, setFormdata] = useState(
{
lis:[],
videos:[
{
iframe:"",
ressort:"",
timestamp:"",
theme:"",
title:""
},
{
iframe:"",
ressort:"",
timestamp:"",
theme:"",
title:""
},
{
iframe:"",
ressort:"",
timestamp:"",
theme:"",
title:""
}
],
themen:[],
}
);
const {lis, videos,themen} = formdata;
const handleChange = (e)=>{
setFormdata((prevState)=>({
...prevState,
[e.target.name]: e.target.value,
}))
}
const onSubmit = (e)=>{
e.preventDefault();
const dropdownRessortData = {
lis,
videos,
themen,
}
dispatch(createDropdownRessort(dropdownRessortData));
}
if(isLoading){
return <Spinner/>
}
return (
<Container>
<CrudTitleHolder>
<CrudTitle>Dropdown Menü Ressort</CrudTitle>
</CrudTitleHolder>
<DataformDropDownRessort onSubmit={onSubmit}>
{dropdownRessort.length > 0 && <DataHolder>
{dropdownRessort.map((item)=>(
<div key={item._id}>
{console.log(item._id)}
<h4 id="name">{item.name}</h4>
<div id="listenpunkte">Menüpunkte: {item.lis.join(", ")}<span style={{color:"var(--red)"}}> Bitte nur nach Absprache verändern.</span></div>
<VideoWrapper>
<DataVideoholder>
<iframe src={item.videos[0].iframe} title={item.videos[0].title}/>
<h4>{item.videos[0].ressort}</h4>
<h4>{item.videos[0].theme}</h4>
<p>{item.videos[0].title}</p>
</DataVideoholder>
<DataVideoholder>
<iframe src={item.videos[1].iframe} title={item.videos[0].title}/>
<h4>{item.videos[1].ressort}</h4>
<h4>{item.videos[1].theme}</h4>
<p>{item.videos[1].title}</p>
</DataVideoholder>
<DataVideoholder>
<iframe src={item.videos[2].iframe} title={item.videos[0].title}/>
<h4>{item.videos[2].ressort}</h4>
<h4>{item.videos[2].theme}</h4>
<p>{item.videos[2].title}</p>
</DataVideoholder>
</VideoWrapper>
<Themen>Themen: {item.themen.join(", ")}</Themen>
<DataButtonHolder>
<Link to={`/dropdownressortedit/${item._id}`}className="link">
<DataUpdateButton>Update</DataUpdateButton>
</Link>
<DataDeleteButton onClick={()=>dispatch(deleteDropdownRessort(item._id))}>Löschen</DataDeleteButton>
</DataButtonHolder>
</div>
))}
</DataHolder>}
<section className="menupoints" encType="multipart/form-data">
<DataLabel htmlFor="lis_ressorts">Menüpunkte Ressorts</DataLabel>
<DataInput type="text" name="lis_ressorts" id="lis_ressorts" value={lis} onChange={handleChange}/>
</section>
<div className="videos">
<section className="video_1">
<DataLabel htmlFor="ressortvideo_1_iframe">Video 1</DataLabel>
<DataInput type="file" name="ressortvideo_1_iframe" id="video_1_iframe"
style={{background:"var(--blue)", color:"var(--white)"}}
value={videos[0].iframe} onChange={handleChange}/>
<DataLabel htmlFor="video_1_ressort">Video 1 Ressortzuordnung</DataLabel>
<DataInput type="text" name="video_1_ressort" id="video_1_ressort" value={videos[0].ressort} onChange={handleChange}/>
<DataLabel htmlFor="video_1_theme">Video 1 Themenzuordnung</DataLabel>
<DataInput type="text" name="video_1_theme" id="video_1_theme" value={videos[0].theme} onChange={handleChange}/>
<DataLabel htmlFor="video_1_title">Video 1 Titelzuordnung</DataLabel>
<DataInput type="text" name="video_1_title" id="video_1_title" value={videos[0].title} onChange={handleChange}/>
</section>
<section className="video_2">
<DataLabel htmlFor="ressortvideo_2_iframe">Video 2</DataLabel>
<DataInput type="file" name="ressortvideo_2_iframe" id="video_2_iframe"
style={{background:"var(--blue)", color:"var(--white)"}}
value={videos[1].iframe} onChange={handleChange}/>
<DataLabel htmlFor="video_2_ressort">Video 2 Ressortzuordnung</DataLabel>
<DataInput type="text" name="video_1_ressort" id="video_2_ressort" value={videos[1].ressort} onChange={handleChange}/>
<DataLabel htmlFor="video_2_theme">Video 2 Themenzuordnung</DataLabel>
<DataInput type="text" name="video_2_theme" id="video_2_theme" value={videos[1].theme} onChange={handleChange}/>
<DataLabel htmlFor="video_2_title">Video 2 Titelzuordnung</DataLabel>
<DataInput type="text" name="video_2_title" id="video_2_title" value={videos[1].title} onChange={handleChange}/>
</section>
<section className="video_3">
<DataLabel htmlFor="ressortvideo_3_iframe">Video 3</DataLabel>
<DataInput type="file" name="ressortvideo_3_iframe" id="video_3_iframe"
style={{background:"var(--blue)", color:"var(--white)"}}
value={videos[2].iframe} onChange={handleChange}/>
<DataLabel htmlFor="video_3_ressort">Video 3 Ressortzuordnung</DataLabel>
<DataInput type="text" name="video_3_ressort" id="video_3_ressort" value={videos[2].ressort} onChange={handleChange}/>
<DataLabel htmlFor="video_3_theme">Video 3 Themenzuordnung</DataLabel>
<DataInput type="text" name="video_3_theme" id="video_3_theme" value={videos[2].theme} onChange={handleChange}/>
<DataLabel htmlFor="video_3_title">Video 3 Titelzuordnung</DataLabel>
<DataInput type="text" name="video_3_title" id="video_3_title" value={videos[2].title} onChange={handleChange}/>
</section>
</div>
<section className="themen">
<DataLabel htmlFor="themen_ressorts">Themen</DataLabel>
<DataInput type="text" name="themen_ressorts" id="themen_ressorts" value={themen} onChange={handleChange}/>
</section>
<DataButtonHolder>
<DataSendButton type="submit">Absenden</DataSendButton>
</DataButtonHolder>
</DataformDropDownRessort>
</Container>
)
}
export default DropdownRessorts
Here is my edit-component:
const DropdownRessortEdit = () => {
const dispatch = useDispatch();
const {dropdownRessort, isLoading, isError, message} = useSelector((state)=>state.dropdownRessort);
const { id } = useParams();
const [data, setData] = useState({
lis: [],
videos:[
{
iframe:"",
ressort:"",
theme:"",
title:"",
},
{
iframe:"",
ressort:"",
theme:"",
title:"",
},
{
iframe:"",
ressort:"",
theme:"",
title:"",
},
],
themen:[],
})
const {lis, videos, themen} = data;
useEffect(()=>{
if(isError){
window.alert(message);
}
dispatch(getDropdownRessort(id));
return ()=>{
dispatch(reset());
}
}, [dispatch, isError, message, id]);
const updateData = (value)=>{
return setData((prev) =>{
return { ...prev, ...value}
})
}
const onSubmit = (e)=>{
e.preventDefault();
const updateDropdownRessortData = {
lis,
videos,
themen,
}
dispatch(updateDropdownRessort(updateDropdownRessortData));
}
if(isLoading){
return <Spinner/>
}
return (
<Container>
<Navbar/>
<TitleHolder>
<Title>Update DropdownRessort</Title>
</TitleHolder>
<ContentHolder>
<UpdateForm onSubmit={onSubmit} encType="multipart/form-data">
{dropdownRessort.length > 0 && <DataHolder>
{dropdownRessort.map((item)=>(
<div key={item._id}>
<Label htmlFor="name">Name</Label>
<Input type="text" name="name" id="name" value={item.name} onChange={(e)=>updateData({name: e.target.value})}/>
<Label htmlFor="lis">MenüPunkte</Label>
<Input type="text" name="lis" id=""lis value={item.lis.join(", ")} onChange={(e)=>updateData({lis: e.target.value})}/>
<VideoWrapper>
<VideoSection>
<Label htmlFor="ressortvideo_1_iframe">Video 1 update</Label>
<Input type="text" name="ressortvideo_1_iframe" id="iframe" value={item.videos[0].iframe} onChange={(e)=>updateData({iframe: e.target.value})}/>
<Label htmlFor="ressort">Ressort</Label>
<Input type="text" name="ressort" id="ressort" value={item.videos[0].ressort} onChange={(e)=>updateData({ressort: e.target.value})}/>
<Label htmlFor="theme">Thema</Label>
<Input type="text" name="theme" id="theme" value={item.videos[0].theme} onChange={(e)=>updateData({theme: e.target.value})}/>
<Label htmlFor="title">title</Label>
<Input type="text" name="title" id="title" value={item.videos[0].title} onChange={(e)=>updateData({title: e.target.value})}/>
</VideoSection>
<VideoSection>
<Label htmlFor="ressortvideo_2_iframe">Video 2 update</Label>
<Input type="text" name="ressortvideo_2_iframe" id="iframe" value={data.videos[1].iframe} onChange={(e)=>updateData({iframe: e.target.value})}></Input>
<Label htmlFor="ressort">Ressort</Label>
<Input type="text" name="ressort" id="ressort" value={item.videos[1].ressort} onChange={(e)=>updateData({ressort: e.target.value})}/>
<Label htmlFor="theme">Thema</Label>
<Input type="text" name="theme" id="theme" value={item.videos[1].theme} onChange={(e)=>updateData({theme: e.target.value})}/>
<Label htmlFor="title">title</Label>
<Input type="text" name="title" id="title" value={item.videos[1].title} onChange={(e)=>updateData({title: e.target.value})}/>
</VideoSection>
<VideoSection>
<Label htmlFor="ressortvideo_3_iframe">Video 3 update</Label>
<Input type="text" name="ressortvideo_3_iframe" id="iframe" value={item.videos[2].iframe} onChange={(e)=>updateData({iframe: e.target.value})}></Input>
<Label htmlFor="ressort">Ressort</Label>
<Input type="text" name="ressort" id="ressort" value={item.videos[2].ressort} onChange={(e)=>updateData({ressort: e.target.value})}/>
<Label htmlFor="theme">Thema</Label>
<Input type="text" name="theme" id="theme" value={item.videos[2].theme} onChange={(e)=>updateData({theme: e.target.value})}/>
<Label htmlFor="title">title</Label>
<Input type="text" name="title" id="title" value={item.videos[2].title} onChange={(e)=>updateData({title: e.target.value})}/>
</VideoSection>
</VideoWrapper>
<Label htmlFor="themen">Themen</Label>
<Input type="text" name="themen" id="themen" value={item.themen} onChange={(e)=>updateData({themen: e.target.value})}/>
<ButtonHolder>
<UpdateButton type="submit">Update</UpdateButton>
</ButtonHolder>
</div>
))}
</DataHolder>
}
</UpdateForm>
</ContentHolder>
<Footer/>
</Container>
)
}
export default DropdownRessortEdit
Solution 1:[1]
Try to remove dispatch from the dependencies in useEffect hook.
Because you want to fetch dispatch only when the component mount, not each time dispatch is changed.
So, in your code case, it will change dispatch which will re-trigger the hook which will fetch dispatch again which will change dispatch causes the hook to re-trigger and so on .. causing Infinity Loop.
Solution 2:[2]
You can try to put dispatch in a React.useCallback
function as shown in this example w3school React.useCallback
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | FaFa |