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))
然后返回错误:
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
有人碰巧知道这里是什么问题吗?
答案 0 :(得分:7)
在包含- (void)createCVBufferWithSize:(CGSize)size
withRenderTarget:(CVPixelBufferRef *)target
withTextureOut:(CVOpenGLESTextureRef *)texture {
CVReturn err = CVOpenGLESTextureCacheCreate(kCFAllocatorDefault, NULL, _context, NULL, &_textureCache);
if (err) return;
CFDictionaryRef empty;
CFMutableDictionaryRef attrs;
empty = CFDictionaryCreate(kCFAllocatorDefault,
NULL,
NULL,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
attrs = CFDictionaryCreateMutable(kCFAllocatorDefault, 1,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
CFDictionarySetValue(attrs, kCVPixelBufferIOSurfacePropertiesKey, empty);
CVPixelBufferCreate(kCFAllocatorDefault, size.width, size.height,
kCVPixelFormatType_32BGRA, attrs, target);
CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
_textureCache,
*target,
NULL, // texture attributes
GL_TEXTURE_2D,
GL_RGBA, // opengl format
size.width,
size.height,
GL_BGRA, // native iOS format
GL_UNSIGNED_BYTE,
0,
texture);
CFRelease(empty);
CFRelease(attrs);
}
的{{1}}语句之后,您的代码等效于:
if
这意味着它是有条件执行的(仅当未执行return
时)。
要解决:
if(!firebase.getCurrentUsername()) {
...
return null
} else {
useEffect(...)
...
}
答案 1 :(得分:1)
请勿在循环,条件或嵌套函数中调用Hook。相反,请始终在您的React函数的顶层使用挂钩。 您可以遵循文档here。
在上面的代码中找不到用例。如果您需要在firebase.getCurrentUsername()
的返回值更改时运行效果,则可能希望在if
条件之外使用它,例如:
useEffect(() => {
firebase.getCurrentUserQuote().then(setQuote)
}, [firebase.getCurrentUsername()]);
答案 2 :(得分:1)
我认为有一种方法可以有条件地调用钩子。您只需要从该挂钩中导出一些成员即可。将此代码段复制并粘贴到codeandbox中:
import React from "react";
import ReactDOM from "react-dom";
function useFetch() {
return {
todos: () =>
fetch("https://jsonplaceholder.typicode.com/todos/1").then(response =>
response.json()
)
};
}
const App = () => {
const fetch = useFetch(); // get a reference to the hook
if ("called conditionally") {
fetch.todos().then(({title}) =>
console.log("it works: ", title)); // it works: delectus aut autem
}
return null;
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
答案 3 :(得分:0)
这里的问题是,当我们从null
返回if block
时,useEffect
钩子代码将无法访问,因为我们之前返回了钩子代码,因此错误是被有条件地调用。
您可能想先定义所有的钩子,然后开始编写用于渲染的逻辑,无论是null还是空字符串,还是有效的JSX。