javascript - 从 NextJS 中的 _app 访问 React 上下文 API
问题描述
我需要访问_app.js
文件中的上下文 API 以设置由路由器事件触发的全局状态。这样做的原因是设置一个加载状态,该状态可由整个应用程序中的各个组件访问。问题是上下文是从文件中提供的_app.js
,所以我没有上下文的上下文。
context.js
import React, { createContext, useState } from "react";
export const Context = createContext();
const ContextProvider = (props) => {
const [isLoading, setIsLoading] = useState(false);
return (
<Context.Provider
value={{
isLoading,
setIsLoading,
}}
>
{props.children}
</Context.Provider>
);
};
export default ContextProvider;
_app.js
import React, { useContext } from "react";
import App from "next/app";
import Head from "next/head";
import Aux from "../hoc/Aux";
import ContextProvider, { Context } from "../context/context";
import { withRouter } from "next/router";
class MyApp extends App {
static contextType = Context;
componentDidMount() {
this.props.router.events.on("routeChangeStart", () => {
this.context.isLoading(true);
});
this.props.router.events.on("routeChangeComplete", () => {
this.context.isLoading(false);
});
this.props.router.events.on("routeChangeError", () => {
this.context.isLoading(false);
});
}
render() {
const { Component, pageProps } = this.props;
return (
<Aux>
<Head>
<title>My App</title>
</Head>
<ContextProvider>
<Component {...pageProps} />
</ContextProvider>
</Aux>
);
}
}
export default withRouter(MyApp);
显然这行不通,因为_app.js
它没有包含在上下文提供程序中。我已经尝试将路由器事件侦听器移到组件树的下方,但是我没有以这种方式将加载状态从主页获取到动态创建的页面。
是否有任何解决方法可以让我使用上下文_app.js
?我想不出任何其他方式可以全局访问加载状态以有条件地加载特定组件。
解决方案
我不清楚为什么您需要上下文提供者成为_app.js
(或完全是单独的组件)的父级。下面的工作不行吗?
class MyApp extends App {
state = {
isLoading: false,
};
componentDidMount() {
this.props.router.events.on("routeChangeStart", () => {
this.setIsLoading(true);
});
this.props.router.events.on("routeChangeComplete", () => {
this.setIsLoading(false);
});
this.props.router.events.on("routeChangeError", () => {
this.setIsLoading(false);
});
}
render() {
const { Component, pageProps } = this.props;
return (
<Aux>
<Head>
<title>My App</title>
</Head>
<Context.Provider
value={{
isLoading: this.state.isLoading,
setIsLoading: this.setIsLoading,
}}>
<Component {...pageProps} />
</Context.Provider>
</Aux>
);
}
setIsLoading = (isLoading) => {
this.setState({ isLoading });
}
}
export default withRouter(MyApp);
或者(如果我真的不了解您的用例),您可以创建一个 HoC:
function withContext(Component) {
return (props) => (
<ContextProvider>
<Component {...props} />
</ContextProvider>
);
}
class MyApp extends App {
...
}
export default withContext(withRouter(MyApp));
推荐阅读
- javascript - 在 HTML 中,name="object[prop]" 似乎不起作用
- c# - 使用带有 C# 的 Nordic nRF52840 (BLE) 的经验/示例?
- python - Pandas - 替换缺失值并同时根据列添加前缀或后缀?
- node.js - Node wss Websocket 在桌面上工作,而不是在移动设备上
- python - 网络抓取 Tennis24 的比赛统计数据
- javascript - 在表单 Post 上添加动态输入时遇到问题
- javascript - 如何从 php 运行 javascript 代码(提交后重新显示隐藏字段)
- yaml - 在 YAML 中使用 Fn::GetAtt 时,流集合条目之间缺少逗号
- php - PHP | 如何从远程服务器下载和提取 ZIP 文件?
- reactjs - 反应选择 - setData