反应配置变量的异步加载

时间:2017-05-16 22:14:07

标签: reactjs react-native auth0

我对React很新,我似乎无法解决一个简单的问题。我正在实现auth0锁定小部件,并已将其导入我的' routes.js'如下:

routes.js

import {requireAuth} from './js/helpers/AuthService.js';

我的AuthService.js没有构造函数,它只包含函数的声明,其中一些必须导出。片段:

AuthService.js

  const lock = new Auth0Lock(
  client_id,
  domain, {
    auth: {
      redirectUrl: `${window.location.origin}${LOGIN_ROUTE}`,
      responseType: 'token id_token',
        params: {
         scope: 'openid email' 
      },
    }
  }
);

const events = new EventEmitter();

lock.on('authenticated', authResult => {
  setAccessToken(authResult.accessToken);
  lock.getUserInfo(authResult.accessToken, (error, profile) => {
    if (error) { return setProfile({error}); }
    setProfile(profile);
    browserHistory.push(getNextPath());
    clearNextPath();
  });
});

export function login(options) {
  lock.show(options);

  return {
    hide() {
      lock.hide();
    }
  }
}
(etc.)

我唯一想要实现的是加载' client_id'和'域名'变量通过API调用,在其他所有加载之前。所以基本上是这样的:

# fetch the config variables
fetch(url)
    .then(function(response) {
    if (response.status >= 400) {
       throw new Error("Bad response from server");
    }
    return response.json();
  })
  .then(function(data) {
     const client_id = data.client_id
     const domain = data.domain
  });

  # Proceed with normal flow
  const lock = new Auth0Lock(
  client_id,
  domain, {
    auth: {
      redirectUrl: `${window.location.origin}${LOGIN_ROUTE}`,
      responseType: 'token id_token',
        params: {
         scope: 'openid email' 
      },
    }
  }
);

我遇到的问题是fetch是一个异步调用,所以其他代码不等待它完成,这会触发其余代码中的错误(client_id和domain是未定义的)。

我已经阅读了有关componentDidMount函数的内容,但总是提到这可以用来延迟渲染。我没有什么可渲染的,我只想宣布一些功能。为此,我只需要根据API调用设置一些常量变量。这不可能,但我似乎无法找到一个好的解决方案。

3 个答案:

答案 0 :(得分:1)

我是React的新手,所以也许你可以等待其他人的确认。

您通过获取获取信息并将其分配给某些变量,但正常流程并不知道那时您所解释的那些变量(或新值)。所以,你可以在这里使用状态。作为一个新的React开发人员,我从一些默认状态开始,在componentDidMount中,我执行Ajax并在那里更改状态(setState)。因此,自状态发生变化后,您的组件将再次被重新渲染。

答案 1 :(得分:0)

您可以在react-async-wrapper

的帮助下加载您的应用之前调用您的异步工作者
import React from 'react';
import { AsyncComponent } from 'react-async-wrapper';

export default class AsyncApp extend React.Component {
    render() {
        return (
            <AsyncComponent asyncProps={{
                lock: () => fetch(url)
                        .then(function(response) {
                            if (response.status >= 400) {
                                throw new Error("Bad response from server");
                            }
                            return response.json();
                        })
                        .then(data => ({
                            new Auth0Lock(
                                data.client_id,
                                data.domain,
                                {
                                    auth: {
                                        redirectUrl: `${window.location.origin}${LOGIN_ROUTE}`,
                                        responseType: 'token id_token',
                                        params: {
                                            scope: 'openid email' 
                                        },
                                    }
                                }
                            )
                        });
            }}>
                <App/> //now in App, you can accept lock by this.props.lock
            </AsyncComponent>
        )
    }
}

答案 2 :(得分:0)

这是一个典型的异步情况,如果您认为所有组件都依赖于fetch()函数调用的输出,则必须在.then()下列出所有组件,例如fetch(url).then( all of your code here) }。

话虽如此,如果你需要根据fetch返回的内容渲染一些组件,你可以在setState({})中使用.then()并相应地在render()方法中调用这些组件