Реагируйте на перенаправление asyc и ожидайте не ждет - PullRequest
0 голосов
/ 12 января 2019

У меня есть следующий код, в котором я хочу получить токен доступа из URL, поместить его в хранилище сеанса и позволить моему дочернему компоненту использовать токен доступа для получения моей информации. Однако, когда компонент загружается в первый раз, он, похоже, не находит токен доступа, а работает, если я обновляю его снова. В попытке решить эту проблему я подумал об использовании async / await, чтобы он не продолжал перенаправлять на дочерний компонент до тех пор, пока не будет установлен токен сеанса, но, похоже, он не ожидает установки токена. Не уверен, что я делаю не так?

class App extends React.Component {
constructor(props){
    super(props);
    this.processToken();
}

componentDidMount() {
   const { user } = this.props; 
   const { accessToken } = user;
   // expecting access token to print here by it is not
   console.log('user token : ', accessToken);
}
 processToken = async () => {
try {
    const params = querySearch(this.props.location.search);
    if('accessToken' in params){
       await new Promise((resolve,reject) => {
          this.setOrderContext(params);
           resolve();
       } );  
        this.props.history.push(`/myinfo`);
    }
} catch(ex) {
  console.log(ex);
}

}

   setOrderContext (params){
     //this action calls a reducer and put the token in session storage
     this.props.userActions.processUserToken({data: {accessToken:params.accessToken}});

}

render() {
    return (

        <Switch>
            //myinfo component needs accessToken to retrieve my info
            <Route path="/myInfo" component={InofUI.App} />
        </Switch>

    );
}

Ответы [ 2 ]

0 голосов
/ 13 января 2019

Вот что у меня сработало.

class App extends React.Component {

componentDidMount() {
   this.processToken();

}
 processToken = () => {
    try {
        const params = querySearch(this.props.location.search);
        if('accessToken' in params){
            this.setOrderContext(params);
            this.props.history.push(`/myinfo`);
        }
    } catch(ex) {
      console.log(ex);
    }
    }

   setOrderContext (params){
     //this action calls a reducer and put the token in session storage
     this.props.userActions.processUserToken({data: {accessToken:params.accessToken}});
}

render() {
    return (

        <Switch>
            //myinfo component needs accessToken to retrieve my info
            <Route path="/myInfo" component={InofUI.App} />
        </Switch>

    );
} 

А потом внутри InfoUI.App

componentDidMount() {
        this.retrieveMyInfo();
    }

    retrieveMyInfo = async () => {
        await this.untilTokenIsSet();
        const { location, history } = this.props;
        this.props.processUser(location, history);
    }

    untilTokenIsSet= () => {
        const poll = (resolve) => {
            const { user } = this.props;
            const { accessToken } = user;
            console.log('getting accessToken', accessToken);
            if (accessToken) {
                resolve();
            } else {
                console.log('wating for token .. ');
                setTimeout(() => poll(resolve), 100);
            }
        };
        return new Promise(poll);
    } 
0 голосов
/ 12 января 2019

Проблема заключается в вызове this.processToken() внутри вашего конструктора. Поскольку вы не ждете и не можете ждать этого вызова, React просто вызывает метод и продолжает его жизненный цикл. Поэтому может случиться так, что componentDidMount вызывается до того, как ваш setOrderContext закончен.

Как всегда в среде React, вы должны извлекать ресурсы и делать асинхронные вызовы внутри componentDidMount. Это гарантирует, что ваш компонент будет отображаться гладко и корректно до того, как будут получены какие-либо внешние ресурсы.

Что вы хотите сделать, это переместить ваш вызов this.processToken() из конструктора в метод componentDidMount и убедиться, что он там обрабатывается правильно.

...