6

i'm new to react and i have the following problem: useEffect is updating infinite times, but i just want it to update the data when i insert a new record, i would be grateful if someone can correct me.

this is my code:

index.js

import {createUser, getUsers} from '../actions';

const Home = () => {
    const [data, setData] = useState([]);

useEffect(() => {
    async function fetchData(){
        const result = await getUsers();
        setData(result);
        console.log("teste: ", result);
    }
    fetchData();
}, [setData]);

const handleCreateUser = (user) => {
    createUser(user).then((users) => {
    });
};

if i put on the second param useEffect(() => {}, [setData]), it breaks the infinite loop but the table does not update when i insert a new register and I need to use F5.

what am i doing wrong? the create user is working perfectly, i just want to att in the same time the table

gabriel graciani
  • 65
  • 1
  • 1
  • 4
  • Where is your table component? Are you using any npm package for it? Add the code for it as well. – pritam Jan 18 '20 at 19:21

5 Answers5

28

In useEffect, without a second parameter (an array of dependencies), your effect will run indefinitely.

If you only want your effect to run when you create a new user, you can make a separate state which is included in the dependencies of useEffect, call it a refreshKey for example. My suggestion would be:

import {createUser, getUsers} from '../actions';

const Home = () => {
    const [data, setData] = useState([]);
    const [refreshKey, setRefreshKey] = useState(0);

useEffect(() => {
    async function fetchData(){
        const result = await getUsers();
        setData(result);
        console.log("teste: ", result);
    }
    fetchData();
}, [refreshKey]);

const handleCreateUser = (user) => {
    createUser(user).then((users) => {
      // Refresh the effect by incrementing 1
      setRefreshKey(oldKey => oldKey +1)
    });
};
Dang Hai Luong
  • 1,316
  • 10
  • 14
2

You can leave the dependancy array blank so it will run only once.

hope this will help you understand better.

   useEffect(() => {
      doSomething()
    }, []) 

empty dependency array runs Only Once, on Mount

useEffect(() => {
  doSomething(value)
}, [value]) 

pass value as a dependency. if dependencies has changed since the last time, the effect will run again.

useEffect(() => {
  doSomething(value)
}) 

no dependency. This gets called after every render.

Shuhad zaman
  • 3,156
  • 32
  • 32
1

It looks like you want to fetch your data only once (on Component Load). If so, just use an empty array for your dependencies

useEffect(() => {
    async function fetchData(){
        const result = await getUsers();
        setData(result);
        console.log("teste: ", result);
    }
    fetchData();
}, []);
Doug
  • 14,387
  • 17
  • 74
  • 104
0

In your example, the second parameter to useEffect should be data; not setData.

lisimba.gilkes
  • 166
  • 1
  • 5
-1

I had the exact problem. I wanted to use a functional component and I had to draw a table after my request came back. If I used [] as the second parameter, the webpage would load one time and hence the chart would not be updated. And when I put something in dependencies i would have had my page reloading indefinitely. I should mention that I put one of my states as the dependency which I defined with useState() hook.

To overcome the situation, I turned my component into a class-based component. This was due to the fact that I wasn't supposed to pass props. But this is not a solution and I can share the code if it helps.

Dharman
  • 30,962
  • 25
  • 85
  • 135