code_dude
code_dude

Reputation: 1111

How can I make react's useEffect to stop rerender in an infinite loop even with a dependency specified?

I am working on a small CRUD fullstack app with react and mongodb and I have this problem where I use useEffect to make an axios get request to the server to get all of my todos. The problem is that useEffect does it's job but it also rerenders to infinity. This is my component:

export default function () {
    ...
    const [todos, setTodos] = useState([]);
    const currentUser = JSON.parse(localStorage.getItem('user'))._id;

    useEffect(() => {
        async function populateTodos () {
            try {
                const res = await axios.get(`http://localhost:8000/api/all-todos/${currentUser}`);
                setTodos(res.data);
            } catch (err) {
               if (err.response) {
                    console.log(err.response.data);
                    console.log(err.response.status);
                    console.log(err.response.headers);
               } else if (err.request) {
                   console.log(err.request);
               } else {
                   console.log('Error: ', err.message);
               }
            }
        }

        populateTodos();
    }, [todos]);

    console.log(todos);

    return (
        ...
    );
}

So what I was expecting to happen is that that console.log to get printed only when the todos changes, like when I add a new todo and so on, but instead it gets printed forever.

Upvotes: 0

Views: 152

Answers (1)

Jolly
Jolly

Reputation: 1768

You said that you need to fetch todos at first, and whenever todos change. I can suggest you a different approach, using one more variable, something like this:

const TodosComponent = (props) => {
    const [todos, setTodos] = useState([]);
    const [updatedTodos, setUpdatesTodos] = useState(true);

    const fetchFunction = () => {
        // In here you implement your fetch, in which you call setTodos().
    }

    // Called on mount to fetch your todos.
    useEffect(() => {
        fetchFunction();
    }, []);

    // Used to updated todos when they have been updated.
    useEffect(() => {
        if (updatedTodos) {
            fetchFunction();
            setUpdatesTodos(false);
        }
    }, [updatedTodos]);

    // Finally, wherever you update your todos, you also write `updateTodos(true)`. 
}

Upvotes: 1

Related Questions