我正在尝试发出可重复使用的 GET 和 POST 请求,但在可重复使用的获取请求组件中设置数据状态时,我收到错误“无效钩子调用”。我刚刚了解到我们只能使用...
我正在尝试制作可重用的 GET
请求 POST
设置状态时 Invalid hook call
出现错误 data
。我刚刚了解到我们只能在 React 组件中使用钩子,那么我该如何使该功能可重用?
import axios from "axios";
import { useContext, useEffect, useState } from "react";
import AuthContext from "../../context/Auth-context/AuthContext";
import { useNavigate } from "react-router-dom";
export const POST = (url, body, credentials) => {
const [data, setData] = useState([]);
const [isLoaded, setIsLoaded] = useState(false);
const [error, setError] = useState(null);
const { dispatch } = useContext(AuthContext);
const navigate = useNavigate();
useEffect(() => {
const fetchData = () => {
axios
.post(url, body, { withCredentials: credentials })
.then((response) => {
setIsLoaded(true);
setData(response.data);
})
.catch((error) => {
if (error.status === 401) {
dispatch({ type: "LOGOUT" });
navigate("/login");
return;
}
setError(error);
});
};
fetchData();
}, [url, credentials, dispatch, navigate, body]);
return { error, isLoaded, data };
};
const approve = async (id) => {
const { data, error, isLoaded } = POST(
"http://localhost:8000/api/new-users",
id,
true
);
if (error) {
return (
<Error/>
);
}
if (!isLoaded) {
return (
<Loader/>
);
}
console.log(data);
};
该代码违反了 React 的 Hooks 规则 。React 钩子(即 useState
, useNavigate
等)只能在 React 函数和自定义 React 钩子中调用,而 POST
这两者都不是。简单的解决方案是简单地重命名 POST
为有效的 React 钩子,例如 "use-"
在标识符上使用前缀。问题是您将调用 usePost
回调,这 再次 违反了 React 的 Hooks 规则。
我建议重构以返回一个处理提取(而不是 useEffect
)的“触发”函数,该函数 可以 在回调中调用。
例子:
export const usePost = (url, credentials) => {
const [data, setData] = useState([]);
const [isLoaded, setIsLoaded] = useState(false);
const [error, setError] = useState(null);
const { dispatch } = useContext(AuthContext);
const navigate = useNavigate();
const trigger = useCallback((body) => {
return axios
.post(url, body, { withCredentials: credentials })
.then((response) => {
setData(response.data);
})
.catch((error) => {
if (error.status === 401) {
dispatch({ type: "LOGOUT" });
navigate("/login");
return;
}
setError(error);
})
.finally(() => {
setIsLoaded(true);
});
}, [url, credentials, dispatch, navigate]);
return { error, isLoaded, data, trigger };
};
用法:
const { data, error, isLoaded, trigger } = usePost(
"http://localhost:8000/api/new-users",
true
);
...
const approve = async (id) => {
trigger(id);
}
...
if (error) {
return <Error />;
}
if (!isLoaded) {
return <Loader />;
}
...