Call a Redux Action inside a useEffect

Asked by At

My objective here is to call an action inside a useEffect.

const ShowTodos = (props) =>{
   useEffect(()=>{
    props.fetchTodos()
   },[])
} 
const mapStateToProps = (state)=>{
  return {
    todos:Object.values(state.todos),
    currentUserId:state.authenticate.userId
  }
}

export default connect(mapStateToProps,{fetchTodos})(ShowTodos)

It works fine but I got a warning

React Hook useEffect has a missing dependency: 'props'. Either include it or remove the dependency array  react-hooks/exhaustive-deps.

But if I'm going to add props as my second parameter in my useEffects then it will run endlessly.

My first workaround here is to use the useRef but it seems that it will always re-render thus re-setup again the useRef which I think is not good in terms of optimization.

const ref = useRef();
  ref.current = props;
  console.log(ref)


  useEffect(()=>{
  ref.current.fetchTodos()
  },[])

Is there any other workaround here ?

2 Answers

1
Shubham Khatri On Best Solutions

That is an eslint warning that you get if any of the dependency within useEffect is not part of the dependency array.

In your case you are using props.fetchTodos inside useEffect and the eslint warning prompts you to provide props as a dependency so that if props changes, the useEffect function takes the updated props from its closure.

However since fetchTodos is not gonna change in your app lifecycle and you want to run the effect only once you can disable the rule for your case.

const ShowTodos = (props) =>{
   const { fetchTodos } = props
   useEffect(()=>{
     fetchTodos()
     // eslint-disable-next-line import/no-extraneous-dependencies
   },[])
} 
const mapStateToProps = (state)=>{
  return {
    todos:Object.values(state.todos),
    currentUserId:state.authenticate.userId
  }
}

export default connect(mapStateToProps,{fetchTodos})(ShowTodos)

You however can solve the problem without disabling the rule like

const ShowTodos = (props) =>{
   const { fetchTodos } = props
   useEffect(()=>{
     fetchTodos()
   },[fetchTodos])
} 

I however will recommend that you know when exactly should you disable the rule or pass the values to the dependency array.

3
Andrej Jurkin On

You have to add fetchTodos to dependencies.

const ShowTodos = ({ fetchTodos }) => {
  useEffect(() => {
    fetchTodos();
  }, [fetchTodos])
  ...
}

or like this.

const ShowTodos = (props) => {
  const { fetchTodos } = props;

  useEffect(() => {
    fetchTodos();
  }, [fetchTodos])
  ...
}