React 上下文值未在 ComponentDidMount 中定义
React context value is not defined in ComponentDidMount
我正在使用 React 和 Context API 将 userId 存储在 Context 中。
我的 ContextProvider 下有一个组件 Authenticator 并将 userId 存储在上下文中,它工作得很好。
但是,我想在另一个组件 MySpace 的上下文中使用此 userId,以获取有关当前用户的一些数据。但是在MySpace的ComponentDidMount()函数中,this.context.userId为null。我认为这是因为我的 ContextProvider 正在执行 setState() 来存储 userId 并且 MySpace 在 setState() 完成之前安装。
这是我的代码,我不知道我是否需要在其他生命周期方法中获取数据。
App.js
class App extends Component {
render() {
return (
<Router history={history}>
<UserContextProvider>
<Authenticator />
<Navbar />
<Switch>
<Route exact path='/' component={Home} />
<Route path='/register' component={Register} />
<Route path='/login' component={Login} />
<PrivateRoute path='/my-space' component={MySpace} />
<Route component={NotFoundPage} />
</Switch>
</UserContextProvider>
</Router>
);
}
}
UserContext.js
export const UserContext = createContext();
class UserContextProvider extends React.Component {
state = {
userId: null
}
replaceUser = (userId) => {
this.setState({ userId: userId });
}
render() {
return (
<UserContext.Provider value={{...this.state, replaceUser: this.replaceUser}}>
{this.props.children}
</UserContext.Provider>
);
}
}
Authenticator.js
class Authenticator extends Component {
static contextType = UserContext;
componentDidMount() {
const { replaceUser } = this.context;
replaceUser(getUserId());
}
render() {
return (
<></>
);
}
}
MySpace.js
class MySpace extends Component {
static contextType = UserContext;
componentDidMount() {
document.title = "Mon espace - Todo";
this.getMyProjects();
}
getMyProjects = () => {
const { userId } = this.context
console.log(userId) // => null
_getMyProjects(userId)
.then(projects => {
console.log(projects)
})
.catch(err => alert(err))
}
render() {
return (
<p>Mon espace</p>
)
}
}
您可以在 ContextProvider 获取 userId 并准备好获取数据时捕捉到,在我使用的示例中,您的状态只需要另一个道具 isReady
export const UserContext = createContext();
class UserContextProvider extends React.Component {
state = {
isReady: false,
userId: null
}
replaceUser = (userId) => {
this.setState({ userId: userId, isReady: true });
}
render() {
return (
<UserContext.Provider value={{...this.state, replaceUser: this.replaceUser}}>
{this.props.children}
</UserContext.Provider>
);
}
}
并且在我们的 MySpace 组件中,如果 isReady 标志为真,您需要检查 componentDidUpdate 您可以使用用户 ID 获取数据:
class MySpace extends Component {
static contextType = UserContext;
componentDidMount() {
document.title = "Mon espace -
}
componentDidUpdate(){
if(this.context.isReady){
this.getMyProjects();
}
}
getMyProjects = () => {
const { userId } = this.context
console.log(userId) // => null
_getMyProjects(userId)
.then(projects => {
console.log(projects)
})
.catch(err => alert(err))
}
render() {
return (
<p>Mon espace</p>
)
}
}
我认为这可以解决您的问题,其他方法可能不是创建新道具,而是检查上下文 userId 是否不同于 null,因为 null 是你的初始状态
我正在使用 React 和 Context API 将 userId 存储在 Context 中。
我的 ContextProvider 下有一个组件 Authenticator 并将 userId 存储在上下文中,它工作得很好。
但是,我想在另一个组件 MySpace 的上下文中使用此 userId,以获取有关当前用户的一些数据。但是在MySpace的ComponentDidMount()函数中,this.context.userId为null。我认为这是因为我的 ContextProvider 正在执行 setState() 来存储 userId 并且 MySpace 在 setState() 完成之前安装。
这是我的代码,我不知道我是否需要在其他生命周期方法中获取数据。
App.js
class App extends Component {
render() {
return (
<Router history={history}>
<UserContextProvider>
<Authenticator />
<Navbar />
<Switch>
<Route exact path='/' component={Home} />
<Route path='/register' component={Register} />
<Route path='/login' component={Login} />
<PrivateRoute path='/my-space' component={MySpace} />
<Route component={NotFoundPage} />
</Switch>
</UserContextProvider>
</Router>
);
}
}
UserContext.js
export const UserContext = createContext();
class UserContextProvider extends React.Component {
state = {
userId: null
}
replaceUser = (userId) => {
this.setState({ userId: userId });
}
render() {
return (
<UserContext.Provider value={{...this.state, replaceUser: this.replaceUser}}>
{this.props.children}
</UserContext.Provider>
);
}
}
Authenticator.js
class Authenticator extends Component {
static contextType = UserContext;
componentDidMount() {
const { replaceUser } = this.context;
replaceUser(getUserId());
}
render() {
return (
<></>
);
}
}
MySpace.js
class MySpace extends Component {
static contextType = UserContext;
componentDidMount() {
document.title = "Mon espace - Todo";
this.getMyProjects();
}
getMyProjects = () => {
const { userId } = this.context
console.log(userId) // => null
_getMyProjects(userId)
.then(projects => {
console.log(projects)
})
.catch(err => alert(err))
}
render() {
return (
<p>Mon espace</p>
)
}
}
您可以在 ContextProvider 获取 userId 并准备好获取数据时捕捉到,在我使用的示例中,您的状态只需要另一个道具 isReady
export const UserContext = createContext();
class UserContextProvider extends React.Component {
state = {
isReady: false,
userId: null
}
replaceUser = (userId) => {
this.setState({ userId: userId, isReady: true });
}
render() {
return (
<UserContext.Provider value={{...this.state, replaceUser: this.replaceUser}}>
{this.props.children}
</UserContext.Provider>
);
}
}
并且在我们的 MySpace 组件中,如果 isReady 标志为真,您需要检查 componentDidUpdate 您可以使用用户 ID 获取数据:
class MySpace extends Component {
static contextType = UserContext;
componentDidMount() {
document.title = "Mon espace -
}
componentDidUpdate(){
if(this.context.isReady){
this.getMyProjects();
}
}
getMyProjects = () => {
const { userId } = this.context
console.log(userId) // => null
_getMyProjects(userId)
.then(projects => {
console.log(projects)
})
.catch(err => alert(err))
}
render() {
return (
<p>Mon espace</p>
)
}
}
我认为这可以解决您的问题,其他方法可能不是创建新道具,而是检查上下文 userId 是否不同于 null,因为 null 是你的初始状态