渲染组件之前如何在React中加载服务?

时间:2019-10-06 16:10:49

标签: reactjs

如果我有一个调用某些REST API资源的服务,但是为了获得该API的URL,需要从同一部署站点在本地执行另一个REST调用,并从配置文件中读取该URL。

我在服务的构造函数中进行了该调用,并使用该调用的响应设置了局部变量。

当其他组件尝试调用该服务功能时,问题就开始了,此时URL仍未定义且调用失败。

例如:

服务

    let webServicesBaseUrl;

class ApiService extends EventEmitter {

    // webServicesBaseUrl;

    constructor() {
        super();

        this.getWebServicesBaseUrl().then( (response) => {
            webServicesBaseUrl = response;
            console.log("..........................", webServicesBaseUrl)
        })
    }

 isAuthenticated(/*userName*/) {
        const url = new URL(webServicesBaseUrl + '/SessionManager/isAuthenticated');
        //     params = {user: userName}
        // Object.keys(params).forEach(key => url.searchParams.append(key, params[key]))

        return fetch(url,
            {
                method: 'GET',
                credentials: 'include',
                // mode: "cors",
                headers: headers
            }
        ).then((response) => response.text())
            .then((data) => {
                return data;
            })
            .catch(console.log);
    }}

export const service = new ApiService();

组件

import {service} from "../stores/RestService";
componentWillMount() {

    service.isAuthenticated(/*this.props.user*/).then((response) => {
        if (response !== 'true') {
            this.props.history.push('/login')
        }
    });

获取:

enter image description here

2 个答案:

答案 0 :(得分:1)

您可以创建一个初始状态,例如isUrlReady:false,然后在收到信息时将其设置为true。然后执行以下操作:

    if(this.state.isUrlReady){
set your const here
return some data after the config
} else {
return (<p>loading</p>); // example
}

您也可以使用React挂钩来做到这一点。 https://reactjs.org/docs/hooks-intro.html

答案 1 :(得分:0)

问题1:

似乎isAuthenticated是异步函数。

最好在componentDidMount中调用它。

axios中具有访存或componentWillMount的API调用在第一个渲染之前不会返回。这意味着组件将使用空数据至少渲染一次。

不推荐使用componentWillMount,不推荐使用。

请在componentDidMount中尝试。

问题2: 不要在构造函数中提取。

最好在webServicesBaseUrl函数中获取isAuthenticated

 authenticateByService(baseUrl) {
    // Haha! here it is. You can now use baseUrl here and verify the user!
 }

 isAuthenticated() {
   if (this.webServicesBaseUrl) {
      authenticateByService(this.webServicesBaseUrl);
      return;
   }
   this.getWebServicesBaseUrl().then( (response) => {
     this.webServicesBaseUrl = response;
     authenticateByService(this.webServicesBaseUrl);
   })
 }

编辑:

    constructor() {
        super();

        this.getWebServicesBaseUrl().then( (response) => {
            webServicesBaseUrl = response; // THIS IS THE REASON!!!
        })
    }

    isAuthenticated(/*userName*/) {
        // webServiesBaseUrl is undefined
        const url = new URL(webServicesBaseUrl + '/SessionManager/isAuthenticat')
    ...

您必须使用webServiesBaseUrl来代替普通的this.webServicesBaseUrl

this.webServicesBaseUrl = response;
...
const url = new URL(this.webServicesBaseUrl + '/SessionManager/isAuthenticat')