You need to parse your news only when there is a change in new props. Add another useEffect with news as a dependency so it will be called when the news changes and then update your state there.
import React, {useEffect, useState} from 'react';
import Carousel from 'react-bootstrap/Carousel';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import {getNews} from "../../actions/news";
import Parser from 'rss-parser';
const NewsCarousel = ({getNews, news: {news, loading} }) => {
const [getFeed, setFeed] = useState({
feed: ''
});
useEffect(() => {
const interval = setInterval(() => {
getNews();
}, 5000);
return () => clearInterval(interval);
}, [getNews]);
useEffect(() => {
const newsFeed = feed => setFeed({ ...getFeed, feed: feed });
const parser = new Parser();
parser.parseString(news, function(err, feed){
if (!err) {
newsFeed(feed);
} else {
console.log(err);
}
});
}, [news]);
return (
<div className="dark-overlay">
</div>
);
};
NewsCarousel.propTypes = {
getNews: PropTypes.func.isRequired,
news: PropTypes.object.isRequired
};
const mapStateToProps = state => ({
news: state.news
});
export default connect(mapStateToProps, {getNews}) (NewsCarousel);
Answer from Amit Chauhan on Stack OverflowuseState setting an infinite loop
Infinite loop with useState + useRecoilState
reactjs - React useState Causing an infinite loop - Stack Overflow
useEffect causes an infinite loop?
Videos
Passing an empty array as the second argument to useEffect makes it only run on mount and unmount, thus stopping any infinite loops.
useEffect(() => {
setIngredients({});
}, []);
This was clarified to me in the blog post on React hooks at https://www.robinwieruch.de/react-hooks/
Had the same problem. I don't know why they not mention this in docs. Just want to add a little to Tobias Haugen answer.
To run in every component/parent rerender you need to use:
useEffect(() => {
// don't know where it can be used :/
})
To run anything only one time after component mount(will be rendered once) you need to use:
useEffect(() => {
// do anything only one time if you pass empty array []
// keep in mind, that component will be rendered one time (with default values) before we get here
}, [] )
To run anything one time on component mount and on data/data2 change:
const [data, setData] = useState(false)
const [data2, setData2] = useState('default value for first render')
useEffect(() => {
// if you pass some variable, than component will rerender after component mount one time and second time if this(in my case data or data2) is changed
// if your data is object and you want to trigger this when property of object changed, clone object like this let clone = JSON.parse(JSON.stringify(data)), change it clone.prop = 2 and setData(clone).
// if you do like this 'data.prop=2' without cloning useEffect will not be triggered, because link to data object in momory doesn't changed, even if object changed (as i understand this)
}, [data, data2] )
How i use it most of the time:
export default function Book({id}) {
const [book, bookSet] = useState(false)
const loadBookFromServer = useCallback(async () => {
let response = await fetch('api/book/' + id)
response = await response.json()
bookSet(response)
}, [id]) // every time id changed, new book will be loaded
useEffect(() => {
loadBookFromServer()
}, [loadBookFromServer]) // useEffect will run once and when id changes
if (!book) return false //first render, when useEffect did't triggered yet we will return false
return <div>{JSON.stringify(book)}</div>
}
Hello, I'm pretty new to React so I will try to explain my issue the best I can.
I have a component <Equation /> nested in <Picker />
I am trying to click a button inside of <Picker /> and have useState() update content inside of <Equation />.
I have a state set with const [operator, setOperator] = React.useState("+") inside of the Picker component that works fine , <Equation operation={operator} /> up until I add setOperator() to the onClick in the button.
<button className="Picker" onClick={(setText("Addition"), setOperator("+"))} >
Once I add this to the element I get this error
Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
Here is is a link to the Components https://gist.github.com/tbednarz/20f166f1ad8161d24b02ae30bded0cd2
Problem is here updateState({...state, name: 'something'}) , you're updating state the before even it's rendering and that continues the updates the state, which will re-render, it goes on. Use useEffect to update the state.
useEffect(() => {
updateState({...state, name: 'something'});
}, [])
The issue is that you are updating the state on every render using updateState({...state, name: 'something'});, which then triggers a new render, etc etc.
If you want the state to contain multiple variables, you have two main options.
Use multiple useState hooks:
export default function App() {
const [dishes, setDishes] = useState(DISHES)
const [name, setName] = useState('something')
return <div></div>
}
Or, since you are using an object for your current state, you could just add more properties:
export default function App() {
const [state, updateState] = useState({
dishes: DISHES,
name: 'something'
});
return <div></div>
}
This second method will work, but React will not do deep comparison between object states, so it's generally more efficient to use the first method.
Hey!! First time building a website and have ran into this issue when trying to fetch content from Sanity Studio.
Here's the link: https://pastebin.com/3iL0gpBt
Copying what I think is the relevant part of the code
export default function IssuesList() {
const [items, setItems] = useState([]);
useEffect(() => {
sanityClient
.fetch(
`*[_type == "issue"] | order(publishedAt desc) {
title,
slug,
description,
frontCover{
asset->{
_id,
url
}
}
}`
)
.then((data) => {
setItems(data);
})
.catch(console.error);
});
return (
<div css={issuesListSx}>
<Frame path={[{ name: "Issues", slug: "/issues" }]}>
<Grid gap={2} columns={[1, null, 2]} className="issuesGrid">
{items.map((issue) => {
return (
<div className="issueItem" key={issue.title}>
<Link to={"/issues/" + issue.slug.current}>
<div>{issue.title}</div>
{issue.frontCover && "asset" in issue.frontCover && (
<img src={issue.frontCover.asset.url} alt="" />
)}
</Link>
</div>
);
})}
</Grid>
</Frame>
</div>
);
}E: Fixed!! Had to add an empty array as a second parameter to useEffect
This is the offending code:
const [users, setUsers] = useState([]);
cognitoidentityserviceprovider.listUsers(params, (err, data) => {
if (err) {
console.log(err);
} else {
setUsers(data.Users);
console.log(data);
}
});I really see no reason as to why this will send the code into an infinite loop but it does for some reason. I tried calling it within useEffect, but passing an empty array or [users] to it does nothing at all, and no array sends it into a loop again.
Is there something I'm just misunderstanding about Hooks here?