在 React 中导入组件时出现无效挂钩调用错误
Getting Invalid hook call error on importing a component in React
我建立了一个登录页面,在其中填写用户名和密码并点击提交按钮后,它会发送基本上转到后端的操作并检查用户名和密码是否有效。我正在使用 React
和 redux
,下面是我的登录页面
login.js(简体)
import LoginHandle from '../login/LoginHandle'
function userLogin(event) {
event.preventDefault()
const username = document.getElementById("username").value
const password = document.getElementById("password").value
LoginHandle(username, password)
}
const Login = () => {
return (
<div className="flex-row align-items-center">
<form onSubmit={(e) => userLogin(e)}>
<h1>Login</h1>
<input id="username" type="email" placeholder="Username" required/>
<input id="password" type="password" placeholder="Password" required/>
<button type="submit" className="px-4">Login</button>
</form>
</div>
)
}
export default Login
LoginHandle.js(简体)
import {useDispatch, useSelector} from 'react-redux'
import {getLoginStatus} from '../actions/loginAction'
const LoginHandle = (username, password) => {
const dispatch = useDispatch()
dispatch(getLoginStatus(username, password))
const loginState = useSelector(state=> state.loginStatus)
if(loginState.loading) {
console.log("please wait")
}
// .... rest of the logic
}
export default LoginHandle
如您所见,我尝试分派操作,然后检查状态以从后端获得确认。但是我得到这个错误
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:...
我做错了什么?
您在此实现中使用了 2 个挂钩 useDispatch
& useSelector
并在函数内部调用它们,这是无效的用法。挂钩只能在 功能组件 内调用。因此,如下更改上述实现应该可行:
Login.js
import {useDispatch, useSelector} from 'react-redux'
import {getLoginStatus} from '../actions/loginAction'
const Login = () => {
const dispatch = useDispatch()
const loginState = useSelector(state=> state.loginStatus)
function userLogin(event) {
event.preventDefault()
const username = document.getElementById("username").value
const password = document.getElementById("password").value
dispatch(getLoginStatus(username, password))
}
return (
<div className="flex-row align-items-center">
<form onSubmit={(e) => userLogin(e)}>
<h1>Login</h1>
<input id="username" type="email" placeholder="Username" required/>
<input id="password" type="password" placeholder="Password" required/>
<button type="submit" className="px-4">{loginState.loading ? "Please wait..." : "Login"}</button>
</form>
</div>
)
}
export default Login
注意事项:
- 直接在功能组件中调用 useDispatch,而不是在功能组件的函数中调用。然后我们可以在函数中使用 useDispatch 的结果
- 在功能组件内部调用了 useSelector,然后使用输出显示加载以代替按钮中的文本
import {useDispatch, useSelector} from 'react-redux'
import {getLoginStatus} from '../actions/loginAction'
const useLoginHandler = (username, password, submitted) => {
const dispatch = useDispatch();
const loginState = useSelector(state=> state.loginStatus)
// it is better to put the dispatch inside a useEffect rather than outside
useEffect(() => {
if(!submitted) {return};
dispatch(getLoginStatus(username, password))
}, [username, password, submitted]);
if(loginState.loading) {
console.log("please wait")
}
// .... rest of the logic
}
export default useLoginHandler
而且你对钩子的使用是错误的。它不应该在回调函数中。
它应该在顶层。像下面这样的东西。此外,您不应直接访问 dom 元素,而应使用 useRef 或 useState 获取值
const Login = () => {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('')
const [submitted, setSubmitted] = useState(false);
useLoginHandler(username, password, submitted); //custom hook should be used at this level
return (
<form onSubmit={(e) => setSubmitted(true)}>
<input id="username" type="email" placeholder="Username" required onChange={e => setUsername(e.target.value)}/>
</form>
)
}
我建立了一个登录页面,在其中填写用户名和密码并点击提交按钮后,它会发送基本上转到后端的操作并检查用户名和密码是否有效。我正在使用 React
和 redux
,下面是我的登录页面
login.js(简体)
import LoginHandle from '../login/LoginHandle'
function userLogin(event) {
event.preventDefault()
const username = document.getElementById("username").value
const password = document.getElementById("password").value
LoginHandle(username, password)
}
const Login = () => {
return (
<div className="flex-row align-items-center">
<form onSubmit={(e) => userLogin(e)}>
<h1>Login</h1>
<input id="username" type="email" placeholder="Username" required/>
<input id="password" type="password" placeholder="Password" required/>
<button type="submit" className="px-4">Login</button>
</form>
</div>
)
}
export default Login
LoginHandle.js(简体)
import {useDispatch, useSelector} from 'react-redux'
import {getLoginStatus} from '../actions/loginAction'
const LoginHandle = (username, password) => {
const dispatch = useDispatch()
dispatch(getLoginStatus(username, password))
const loginState = useSelector(state=> state.loginStatus)
if(loginState.loading) {
console.log("please wait")
}
// .... rest of the logic
}
export default LoginHandle
如您所见,我尝试分派操作,然后检查状态以从后端获得确认。但是我得到这个错误
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:...
我做错了什么?
您在此实现中使用了 2 个挂钩 useDispatch
& useSelector
并在函数内部调用它们,这是无效的用法。挂钩只能在 功能组件 内调用。因此,如下更改上述实现应该可行:
Login.js
import {useDispatch, useSelector} from 'react-redux'
import {getLoginStatus} from '../actions/loginAction'
const Login = () => {
const dispatch = useDispatch()
const loginState = useSelector(state=> state.loginStatus)
function userLogin(event) {
event.preventDefault()
const username = document.getElementById("username").value
const password = document.getElementById("password").value
dispatch(getLoginStatus(username, password))
}
return (
<div className="flex-row align-items-center">
<form onSubmit={(e) => userLogin(e)}>
<h1>Login</h1>
<input id="username" type="email" placeholder="Username" required/>
<input id="password" type="password" placeholder="Password" required/>
<button type="submit" className="px-4">{loginState.loading ? "Please wait..." : "Login"}</button>
</form>
</div>
)
}
export default Login
注意事项:
- 直接在功能组件中调用 useDispatch,而不是在功能组件的函数中调用。然后我们可以在函数中使用 useDispatch 的结果
- 在功能组件内部调用了 useSelector,然后使用输出显示加载以代替按钮中的文本
import {useDispatch, useSelector} from 'react-redux'
import {getLoginStatus} from '../actions/loginAction'
const useLoginHandler = (username, password, submitted) => {
const dispatch = useDispatch();
const loginState = useSelector(state=> state.loginStatus)
// it is better to put the dispatch inside a useEffect rather than outside
useEffect(() => {
if(!submitted) {return};
dispatch(getLoginStatus(username, password))
}, [username, password, submitted]);
if(loginState.loading) {
console.log("please wait")
}
// .... rest of the logic
}
export default useLoginHandler
而且你对钩子的使用是错误的。它不应该在回调函数中。 它应该在顶层。像下面这样的东西。此外,您不应直接访问 dom 元素,而应使用 useRef 或 useState 获取值
const Login = () => {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('')
const [submitted, setSubmitted] = useState(false);
useLoginHandler(username, password, submitted); //custom hook should be used at this level
return (
<form onSubmit={(e) => setSubmitted(true)}>
<input id="username" type="email" placeholder="Username" required onChange={e => setUsername(e.target.value)}/>
</form>
)
}