未在ComponentDidMount

时间:2019-09-25 13:29:26

标签: javascript reactjs es6-promise

我正在使用React和Context API将userId存储在Context中。

Authenticator 组件位于我的 ContextProvider 下,并将userId存储在上下文中,效果很好。

但是,我想从另一个组件 MySpace 中的上下文中使用此userId,以获取有关当前用户的一些数据。但是在 MySpace 的ComponentDidMount()函数中,this.context.userId为null。我认为这是因为我的ContextProvider正在执行setState()来存储userId,并且在setState()完成之前已安装 MySpace

这是我的代码,我不知道是否需要使用其他生命周期方法获取数据。

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>
        )
    }
}

1 个答案:

答案 0 :(得分:0)

在我的示例中,当使用 isReady

时,您可能会发现ContextProvider何时使用userId并准备好获取数据,只是需要您所在状态的另一个支持。

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>
        );
    }
}

在byour MySpace组件中,您需要在componentDidUpdate中检查isReady标志是否为true,您可以使用用户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 是您的初始状态