Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Hook "useEffect" is called conditionally

React is complaining about code below, saying it useEffect is being called conditionally:

import React, { useEffect, useState } from 'react' import VerifiedUserOutlined from '@material-ui/icons/VerifiedUserOutlined' import withStyles from '@material-ui/core/styles/withStyles' import firebase from '../firebase' import { withRouter } from 'react-router-dom'  function Dashboard(props) {   const { classes } = props      const [quote, setQuote] = useState('')      if(!firebase.getCurrentUsername()) {         // not logged in         alert('Please login first')         props.history.replace('/login')         return null     }      useEffect(() => {         firebase.getCurrentUserQuote().then(setQuote)     })      return (         <main>             // some code here         </main>     )      async function logout() {         await firebase.logout()         props.history.push('/')     } }  export default withRouter(withStyles(styles)(Dashboard))

And that returns me the error:

React Hook "useEffect" is called conditionally. React Hooks must be called in the exact same order in every component render.

Does anyone happen to know what the problem here is?

like image 817
Adalto Picotti Junior Avatar asked Aug 23 '19 06:08

Adalto Picotti Junior


People also ask

Can useEffect be called conditionally?

The error "React hook 'useEffect' is called conditionally" occurs when we use the useEffect hook conditionally or after a condition that may return a value. To solve the error, move all React hooks above any conditionals that may return a value.

Why can t React hooks be called conditionally?

This is not allowed because the number of hooks and the order of hook calls have to be the same on re-renders of our function components. To solve the error, we have to move the useState call to the top level and not conditionally call the hook.

Can hooks be used conditionally?

Don't call Hooks inside loops, conditions, or nested functions. Instead, always use Hooks at the top level of your React function, before any early returns. By following this rule, you ensure that Hooks are called in the same order each time a component renders.

Is useEffect called only once?

useEffect(() => { // Side Effect }, []); In this case, the side effect runs only once after the initial render of the component.


1 Answers

Your code, after an if statement that contains return, is equivalent to an else branch:

if(!firebase.getCurrentUsername()) {     ...     return null } else {     useEffect(...)     ... } 

Which means that it's executed conditionally (only when the return is NOT executed).

To fix:

useEffect(() => {   if(firebase.getCurrentUsername()) {     firebase.getCurrentUserQuote().then(setQuote)   } }, [firebase.getCurrentUsername(), firebase.getCurrentUserQuote()])  if(!firebase.getCurrentUsername()) {   ...   return null } 
like image 185
Aprillion Avatar answered Oct 02 '22 17:10

Aprillion