React上下文(this.context)在构造函数调用时未定义



我正在尝试编写一个类组件,该组件使用this.context中的值来派生状态对象。我有一个方法getStyle,它返回这样一个对象。在constructor的时候,我调用this.getStyle,以一个已经最新的状态开始,并加快初始渲染。

然而,似乎在constructor呼叫时间,this.contextundefined,并且它一直保持到render呼叫时间。

我的代码有错吗?

在React的(新(上下文API文档中,我不记得任何与此问题相关的细节。this.contextcomponentDidMount时间可用,但是,这将需要setState,这将导致额外的组件重新渲染,我希望避免这种情况。

下面是我尝试使用的代码:

import React from "react";
import { View, Text } from "react-native";

const defaultTheme = {
light: { backgroundColor: "white" },
dark: { backgroundColor: "black" }
};
const customTheme = {
light: { backgroundColor: "#EEE" },
dark: { backgroundColor: "#111" },
};
const MyContext = React.createContext(defaultTheme);

class Container extends React.PureComponent {
static contextType = MyContext;
constructor(props) {
super(props);
this.state = this.getStyle();   // TypeError: undefined is not an object (evaluating '_this.context[_this.props.colorScheme || "light"]')
// this.state = {}; // use this to try the componentDidMount alternative
}
componentDidMount = () => {
const style = this.getStyle();
this.setState(style);
}
getStyle = () => {
// this.props.colorScheme = "light" | "dark" | null | undefined
return this.context[this.props.colorScheme || "light"];
}
componentDidUpdate = (prevProps, prevState, snapshot) => {
if (prevProps.colorScheme !== this.props.colorScheme) {
const style = this.getStyle();
this.setState(style);
}
}
render = () => {
return <View style={this.state}>
{this.props.children}
</View>;
}
}

export default function App() {
return <MyContext.Provider value={customTheme}>
<Container>
<Text>Hello, world!</Text>
</Container>
</MyContext.Provider>
}

尝试将上下文传递给构造函数:

constructor(props, context) {
// your code here
}

根据这一点,此解决方案可能会被弃用,但您可以尝试。

对于任何使用React 18+偶然发现这一点的人来说,我能让它工作的唯一方法是访问类组件中render()方法内部的this.conext

除了上面发布的解决方案之外,还有另一个解决方案:上下文包装器组件,将上下文作为道具传递
您创建了一个Wrapper组件,该组件在其呈现函数中使用上下文值,并将其传递给在构造函数时需要这些道具的组件:

class TheActualComponent extends React.PureComponent {
constructor(props) {
super(props);
console.log(props.context); // Now you've got'em
}
// ...
}
// SFC wrapper
function WrapperComponent(props) {
const contextProps = React.useContext(MyContext);
return <TheActualComponent {...props} context={contextProps}>
{props.children}
</TheActualComponent>;
}
// class component wrapper
class WrapperClassComponent extends React.PureComponent {
static contextType = MyContext;
render() {
return <TheActualComponent {...this.props} context={this.context}>
{this.props.children}
</TheActualComponent>;
}
}

最新更新