I really confused about useEffect. sometimes works and sometimes it does not. for example this one,
const [news, setNews] = useState<Array<MainNewsData>>([]);
useEffect(() => {
getNews();
}, []);
const getNews = () => {
NewsService.getMainNews() // calling an api
.then((response: any) => {
setNews(response.data);
})
.catch((e: Error) => {
console.log(e);
});
};
it gives me a React Hook useEffect has a missing dependency: 'getNews'. Either includes it or remove the dependency array
if I add news
will go into an infinite loop.
if I used useRef since I want just one render it works but if I tried to pass the result to another class, would give me an undefined.
What I really don't understand is this code works in a previous project but here not even after reading a lot of examples about how to fetch data using useEffect I still didn't figure out the solution.
one of the answers that I found is to add news.length as a dependency but it's not recommended.
another one is add a timer \:
What I should do? any answer I will appreciate.
CodePudding user response:
Memoise getNews
using useCallback
:
const getNews = React.useCallback(() => {
NewsService
.getMainNews()
.then((response: any) => setNews(response.data))
.catch(console.log)
}, []);
Pass it to the useEffect
dependency array:
useEffect(() => {
getNews();
}, [getNews]);
This now works, because getNews
is always the same function. In your original example, it was recreated after each render due to setting state. That caused the infinite loop.
This answer assumes NewsService
is imported from a different file (or at least declared outside the render cycle), which it looks like it probably is.
CodePudding user response:
Solution
1. Declare function inside useEffect()
useEffect(() => {
function getNews () {
...
}
getNews();
}, [])
2. Disable eslint's warning
useEffect(() => {
getNews()
}, []) // eslint-disable-line react-hooks/exhaustive-deps