reactjs - 错误:无效的挂钩调用。Hooks 只能在函数组件的主体内部调用 - 添加 Loader 组件时
问题描述
我正在做一个 Nextjs - Typescript 项目。我正在尝试添加一个 Loader 组件。页面正在加载加载器组件时为真。否则为假。
这是我的代码:
加载上下文.ts
import React, { useReducer } from "react";
import { NextPage } from "next";
type State = { loading: boolean };
type Action = { type: "startLoading" } | { type: "endLoading" };
type Dispatch = (action: Action) => void;
export const LoadingContext =
React.createContext<{ state: State; dispatch: Dispatch } | undefined>(
undefined
);
const initialState = {
loading: true,
};
const { Provider } = LoadingContext;
const reducer = (state: State, action: Action) => {
switch (action.type) {
case "startLoading":
return {
loading: true,
};
case "endLoading":
return {
loading: false,
};
default:
throw state;
}
};
const LoadingProvider: NextPage = ({ children }) => {
const [state, dispatch] = useReducer(reducer, initialState);
const value = { state, dispatch };
return <Provider value={value}>{children}</Provider>;
};
export function useLoading() {
const context = React.useContext(LoadingContext); // error is somewhere here
if (context === undefined) {
throw new Error("useCount must be used within a CountProvider");
}
return context;
}
export default LoadingProvider;
加载器.tsx
const Loader: NextPage = () => {
return (
<div className={styles.loader_wrapper}>
<div className={styles.content}>
<span className={styles.loading_text}>Loading...</span>
</div>
</div>
);
};
export default Loader;
索引.tsx
import Loader from "../components/Loader/Loader";
import { useLoading } from "../context/LoadingContext";
import { useRouter } from "next/dist/client/router";
const { state, dispatch } = useLoading();
const router = useRouter();
useEffect(() => {
router.events.on("routeChangeStart", () => {
dispatch({ type: "startLoading" });
});
return () => {
router.events.off("routeChangeStart", () => {
dispatch({ type: "endLoading" });
});
};
}, [dispatch, router]);
useEffect(() => {
dispatch({ type: "endLoading" });
}, [dispatch, router]);
const Home: NextPage = () => {
return (
<>
{state.loading ? (
<Loader />
) : (
<>
<div>
// other components
</div>
</>
)}
</>
);
};
我得到了这个错误。错误:无效的挂钩调用。Hooks 只能在函数组件的主体内部调用
我的代码中有哪些错误?
解决方案
您的索引页面正在调用useLoading
,useEffect
并且useRouter
在Home
组件之外。
请参阅反应文档。它清楚地提到了您面临的问题。
Hooks 只能在函数组件的主体内部调用。
它应该是这样的。
import Loader from "../components/Loader/Loader";
import { useLoading } from "../context/LoadingContext";
import { useRouter } from "next/dist/client/router";
const Home: NextPage = () => {
const { state, dispatch } = useLoading();
const router = useRouter();
useEffect(() => {
router.events.on("routeChangeStart", () => {
dispatch({ type: "startLoading" });
});
return () => {
router.events.off("routeChangeStart", () => {
dispatch({ type: "endLoading" });
});
};
}, [dispatch, router]);
useEffect(() => {
dispatch({ type: "endLoading" });
}, [dispatch, router]);
return (
<>
{state.loading ? (
<Loader />
) : (
<>
<div>
// other components
</div>
</>
)}
</>
);
};
推荐阅读
- microsoft-cognitive - 如何让 Speech Studio 使用不同的资源,即 S0 而不是 F0
- java - 如何验证 servlet 处理是否真的在做非阻塞 io?
- entity-framework - 实体框架无法从关联表中删除记录并引发错误
- excel - 包含 VLOOKUP 在内的三个条件的 IF 语句
- c# - 如何在 C# Razor 模板中呈现美化的 JSON?
- node.js - 使用 MERN 堆栈使用 Spotify Web API 进行持久登录
- c# - Array.Exists - 可能的错误?
- android - 我可以在 android 应用程序上使用 Oracle No sql 数据库吗
- flutter - Android 在 Flutter 上的 ViewFlipper 替代方案
- reactjs - React js用材质ui调用路由