Adeel Imran
Adeel Imran

Reputation: 13956

Eslint React Hooks Error: eslint-plugin-react-hooks exhaustive deps warning for a function dependency in useEffect

import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import Actions from '../actions';

export const UserComponent = ({ foo, baz, bar, user, fetchUser }) => {
  useEffect(() => {
    console.log('##### I WAS CALLED I WAS CALLED');
    fetchUser();
  }, []);

  return (
      <div>
        <p>{user.name}</p>
        <p>{foo} {baz} {bar}</p>
      </div>
  );
};

UserComponent.propTypes = {
  fetchUser: PropTypes.func.isRequired,
  user: PropTypes.shape({}),
};

const mapActionsToProps = {
  fetchUser: Actions.fetchUser,
};

const mapStateToProps = ({ data }) => ({
  user: data.user,
});

export default connect(mapStateToProps, mapActionsToProps)(UserComponent);

I get an error 'React Hook useEffect has a missing dependency`

But If I put fetchUser in the dependency array

      useEffect(() => {
        console.log('##### I WAS CALLED I WAS CALLED');
        fetchUser();
      }, [fetchUser]);

It causes an infinite loop.

Upvotes: 1

Views: 10295

Answers (4)

93sauu
93sauu

Reputation: 4107

The problem is that the function fetchUser changes in each render. You can solve the problem using "useCallback".

Example:

const initFetchMethod = useCallback(() => {
   return dispatch(fetchUserAction())
}, [dispatch])


useEffect(() => {
   initFetchMethod();
}, [initFetchMethod]);

References:

Upvotes: 7

Adeel Imran
Adeel Imran

Reputation: 13956

I was using redux the wrong way in hook based components. This guide helped me a lot to use redux in functional components using hooks. https://react-redux.js.org/next/api/hooks

Upvotes: 1

Karan
Karan

Reputation: 285

The error says, you need to put all resources(vars/functions) used by the effect callback inside the dependencies array.

So, you need to put fetchUsers in the dependencies array. But, it will cause infinite loop. Because, fetchUsers instance is recreated everytime.

You need to maintain a loading state for the api response. And, put a check in the callback like below:

useEffect(() => {
    if(!user && !loading ) {
        fetchUser();
    }
}, [fetchUser, user]);

Upvotes: -1

J&#248;rgen
J&#248;rgen

Reputation: 360

Disable the es-lint warning if fetchUser action does not change in app lifecycle

Since fetchUser is an redux action and it is not going to change in your app lifecycle, i would say you can safely disable the rule for your case.

useEffect(() => {
    console.log('##### I WAS CALLED I WAS CALLED');
    fetchUser();
    //eslint-disable-next-line import/no-extraneous-dependencies
  }, []);

Upvotes: -2

Related Questions