javascript React Hook "useEffect" 被有条件地调用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/57620799/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 10:40:07  来源:igfitidea点击:

React Hook "useEffect" is called conditionally

javascriptreactjsreact-hooks

提问by Adalto Picotti Junior

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

React 抱怨下面的代码,说它 useEffect 被有条件地调用:

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:

这让我返回错误:

  Line 48:  React Hook "useEffect" is called conditionally. React Hooks must be called in the exact same order in every component render  react-hooks/rules-of-hooks

Does anyone happen to know what the problem here is?

有谁碰巧知道这里的问题是什么?

回答by Aprillion

Your code, after an ifstatement that contains return, is equivalent to:

if包含的语句之后,您的代码return等效于:

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

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

这意味着它是有条件地执行的(仅当未return执行时)。

To fix:

修理:

useEffect(() => {
  if(firebase.getCurrentUsername()) {
    firebase.getCurrentUserQuote().then(setQuote)
  }
}, [firebase.getCurrentUsername(), firebase.getCurrentUserQuote()])

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

回答by Vishnu

Don't call Hooks inside loops, conditions, or nested functions. Instead, always use Hooks at the top level of your React function. You can follow the documentation here.

不要在循环、条件或嵌套函数中调用 Hook。相反,始终在 React 函数的顶层使用 Hook。您可以按照此处的文档进行操作。

I couldn't find the use case in the above code. If you need the effect to run when the return value of firebase.getCurrentUsername()changes, you might want to use it outside the ifcondition like:

我在上面的代码中找不到用例。如果您需要在返回值firebase.getCurrentUsername()更改时运行效果,您可能希望在if条件之外使用它,例如:

useEffect(() => {
    firebase.getCurrentUserQuote().then(setQuote)
}, [firebase.getCurrentUsername()]);

回答by Anuradha Kumari

The issue here is that when we are returning nullfrom the if block, the useEffecthook code will be unreachable, since we returned before it, and hence the error that it is being called conditionally.

这里的问题是,当我们null从返回时if blockuseEffect钩子代码将无法访问,因为我们在它之前返回,因此有条件地调用它的错误。

You might want to define all the hooks first and then start writing the logic for rendering, be it null or empty string, or a valid JSX.

您可能希望首先定义所有钩子,然后开始编写渲染逻辑,无论是 null 或空字符串,还是有效的 JSX。