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 是你的初始状态