React Invalid Hook Call错误:函数组件外调用Hooks问题排查
错误原因
你碰到的问题是因为useDispatch和useNavigate属于React Hooks,它们只能在函数组件的顶层或者自定义Hook的顶层调用。而你当前的SubmitSignUpForm是普通工具函数,不符合Hook的调用规则,和dispatch本身无关,是调用时机不对导致的报错。
解决方案
方案1:改成自定义Hook
自定义Hook必须以use开头,React会识别它为合法的Hook,允许内部调用其他Hooks:
import axios from "axios"; import { useNavigate } from "react-router-dom"; import { addUser } from "./userInfoSlice"; import { useDispatch } from "react-redux"; // 自定义Hook,命名以use开头 const useSubmitSignUpForm = () => { const dispatch = useDispatch(); const navigate = useNavigate(); const submit = (email, password, name) => { axios.post("https://localhost:44336/api/signin/SignUpUser", { Name: name, Email: email, Password: password }) .then((response) => { console.log(response); dispatch(addUser(response)); navigate("./Browse"); }) .catch((reason) => { console.log(reason); }); }; return submit; }; export default useSubmitSignUpForm;
在组件里的使用方式:
import useSubmitSignUpForm from './useSubmitSignUpForm'; function SignUpComponent() { const submitSignUpForm = useSubmitSignUpForm(); const handleSubmit = () => { // 这里获取表单的email、password、name值 submitSignUpForm(email, password, name); }; return <button onClick={handleSubmit}>注册</button>; }
方案2:把dispatch和navigate作为参数传入
将Hook调用移到组件内部,然后把dispatch和navigate作为参数传给工具函数,让它变成纯逻辑函数:
import axios from "axios"; import { addUser } from "./userInfoSlice"; const SubmitSignUpForm = (email, password, name, dispatch, navigate) => { axios.post("https://localhost:44336/api/signin/SignUpUser", { Name: name, Email: email, Password: password }) .then((response) => { console.log(response); dispatch(addUser(response)); navigate("./Browse"); }) .catch((reason) => { console.log(reason); }); }; export default SubmitSignUpForm;
在组件里的使用方式:
import SubmitSignUpForm from './SubmitSignUpForm'; import { useDispatch } from "react-redux"; import { useNavigate } from "react-router-dom"; function SignUpComponent() { const dispatch = useDispatch(); const navigate = useNavigate(); const handleSubmit = () => { // 这里获取表单的email、password、name值 SubmitSignUpForm(email, password, name, dispatch, navigate); }; return <button onClick={handleSubmit}>注册</button>; }
方案3:把函数写在组件内部
直接将SubmitSignUpForm定义在使用它的函数组件内部,这样就能在组件顶层合法调用Hooks,再在函数里使用:
import axios from "axios"; import { useNavigate } from "react-router-dom"; import { addUser } from "./userInfoSlice"; import { useDispatch } from "react-redux"; function SignUpComponent() { const dispatch = useDispatch(); const navigate = useNavigate(); const SubmitSignUpForm = (email, password, name) => { axios.post("https://localhost:44336/api/signin/SignUpUser", { Name: name, Email: email, Password: password }) .then((response) => { console.log(response); dispatch(addUser(response)); navigate("./Browse"); }) .catch((reason) => { console.log(reason); }); }; const handleSubmit = () => { // 这里获取表单的email、password、name值 SubmitSignUpForm(email, password, name); }; return <button onClick={handleSubmit}>注册</button>; } export default SignUpComponent;
内容的提问来源于stack exchange,提问作者Rocko
相关产品推荐
相关产品推荐

