使用react-router 6.21.1和新的数据api,我的路由设置如下:
const routes = [
{
element: <RootWrapper/>,
errorElement: <ErrorWrapper/>,
children: [
{path: "/login?", element: <LoginWrapper/>},
{path: "/logout", element: <Logout/>},
{
id: "AuthenticatedRoot",
element: <AuthenticatedRoot/>,
children: [
// ...
{path: "/dashboard", element: <Dashboard/>, loader: fetchDashboard},
]
}
]
]
我的仪表板视图 24/7 全天候显示,并且每 5 分钟重新验证一次。它需要在出现最多 5 个错误后保持运行状态,以便为发布或其他未知的停机提供至少 30 分钟的时间。手动使用 useEffects 来获取数据时很简单,因为我可以处理从获取请求返回的错误:
await axios.get('dashboard')
.then(
response => {setData(response.data)},
error => {
setRetries(origRetries => {
if (origRetries >= 6) {
setError(true)
setErrorMessage(error.message)
return 0
} else {
return origRetries + 1
}
})
}
)
有没有办法用新的装载机做这样的事情?
您可以编写
fetchDashboard
加载器函数来关闭重试“状态”。实现可能类似于以下内容:
const fetchDashboard = () => {
let cache = {};
let retry = 0;
return async () => {
try {
const result = await axios.get('dashboard');
// Success, cache result and reset retry state
cache = result;
retry = 0;
return result;
} catch (error) {
// Failure/error, increment retry count
retry++;
if (retry > 5) {
// Rethrow error if ran out of retries
throw error;
} else {
// Otherwise return cached result
return cache;
}
}
};
};
const routes = [
{
element: <RootWrapper />,
errorElement: <ErrorWrapper />,
children: [
{ path: "/login?", element: <LoginWrapper /> },
{ path: "/logout", element: <Logout /> },
{
id: "AuthenticatedRoot",
element: <AuthenticatedRoot />,
children: [
// ...
{
id: "dashboard",
path: "/dashboard",
element: <Dashboard />,
errorElement: <Dashboard />, // <-- render as error element too!
loader: fetchDashboard(), // <-- invoke outer function
},
]
}
],
},
];
import {
useRouteError,
useRouteLoaderData,
useNavigate,
useNavigation
} from "react-router-dom";
const Dashboard = () => {
const navigate = useNavigate();
const { state } = useNavigation(); // "idle"/"loading", could be handy
const data = useRouteLoaderData("dashboard");
const error = useRouteError();
useEffect(() => {
const timer = setInterval(() => {
navigate("/dashboard", { replace: true });
}, 1000 * 60 * 5); // 5 minute interval
return () => clearInterval(timer);
}, []);
useEffect(() => {
console.log("Dashboard", { data, error });
}, [data, error]);
return (
...
);
};