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/
Answer from WhiteFluffy on Stack OverflowPassing 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>
}
useEffect causes an infinite loop?
reactjs - React UseState hook causing infinite loop - Stack Overflow
Infinite loop in useEffect using blank object or array
reactjs - Setting state inside useEffect triggers infinite loop - Stack Overflow
Videos
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