【发布时间】:2021-04-19 22:20:38
【问题描述】:
我有以下上下文提供程序,可让我访问整个应用程序的上下文:
import React, { Component, useContext } from 'react';
import { appInitialization, Context } from "@microsoft/teams-js";
import TeamsContextService from '../Services/TeamsContextService';
import Constants from '../Constants/AppConstants';
const TeamsContext = React.createContext({});
interface Error {
status: boolean,
message: appInitialization.IFailedRequest
}
interface TeamsContextProviderState {
teamsContext : any,
error?: Error
}
class TeamsContextProvider extends Component<{}, TeamsContextProviderState> {
getContext: Function
state: TeamsContextProviderState = {
teamsContext: {},
error: undefined
}
constructor(props: any) {
super(props);
this.getContext = TeamsContextService();
}
componentDidMount() {
this.getContext()
.then((context: Context) => {
const frameContext = context.frameContext || "";
if (frameContext === Constants.Surfaces.SidePanel) {
this.setState({
teamsContext: context,
})
appInitialization.notifySuccess();
return;
}
return Promise.reject("Error: Please make sure to run the app within teams as a tab app");
})
.catch((msg: appInitialization.IFailedRequest) => {
appInitialization.notifyFailure(msg);
this.setState({
error: {
status: true,
message: msg,
}
})
});
}
render() {
return (
<TeamsContext.Provider value={this.state.teamsContext}>
{this.props.children}
</TeamsContext.Provider>
);
}
}
export default TeamsContextProvider;
export const withTeamsContext = (Component: any) => (props: any) => {
const teamsContext = useContext(TeamsContext);
return <Component {...props} teamsContext={teamsContext} />
}
这是由主应用程序使用的:
class App extends Component {
render() {
return (
<Fragment>
<TeamsContextProvider>
<SurfaceSelector/>
</TeamsContextProvider>
</Fragment>
);
}
}
export default App;
在 SurfaceSelector 子组件中,我想访问 TeamsContextProvider teamsContext 属性。然而,在SurfaceSelector 的构造函数中,它为其子属性返回undefined。但是一旦它到达表面选择器的render 功能,那么teamsContext 就会正确填充。我想使用teamsContext 上的theme 属性来更新当前选择的主题,但我不能在构造函数中这样做,因为它是未定义的,并且在渲染中我将无法设置状态没有导致无限循环。有什么办法解决这个问题?我尝试了componentDidUpdate、componentWillUpdate 和其他反应生命周期方法,但如果我尝试更新状态,它们都会以无限循环告终。我尝试了useContext,但我不能在SurfaceSelector 组件中这样做,因为它是一个类组件,需要状态来管理主题。
这里是SurfaceSelector
import { Component, Fragment } from 'react';
import SidePanelPage from '../Pages/SidePanel';
import { withTeamsContext } from '../Contexts/TeamsContextProvider';
import Constants from '../Constants/AppConstants';
import { Context, registerOnThemeChangeHandler } from '@microsoft/teams-js';
import { Provider, teamsDarkV2Theme, teamsHighContrastTheme, ThemeInput} from '@fluentui/react-northstar'
import { i18n } from '@lingui/core'
import { I18nProvider } from '@lingui/react'
import { defaultLocale, dynamicActivate } from '../i18n'
export interface SurfaceSelectorProps {
teamsContext: Context
}
interface SurfaceSelectorState {
theme?: ThemeInput<any>
}
class SurfaceSelector extends Component<SurfaceSelectorProps, SurfaceSelectorState> {
constructor(props: SurfaceSelectorProps) {
super(props)
this.state = {
theme: this.getTheme(this.props.teamsContext.theme)
}
}
private getTheme(theme?: string) {
switch (theme) {
case "dark":
return teamsDarkV2Theme;
case "contrast":
return teamsHighContrastTheme;
}
return teamsDarkV2Theme;
}
render() {
const { SidePanel } = Constants.Surfaces;
const frameContext = this.props.teamsContext.frameContext;
switch (frameContext) {
case SidePanel:
return (
<Fragment>
<I18nProvider i18n={i18n}>
<Provider theme={this.state.theme}>
<SidePanelPage />
</Provider>
</I18nProvider>
</Fragment>
)
default:
return null;
}
}
}
export default withTeamsContext(SurfaceSelector);
【问题讨论】:
标签: reactjs typescript react-hooks