【问题标题】:Using async meteor.call() in meteor-react render() method在meteor-react render() 方法中使用异步meteor.call()
【发布时间】:2016-06-07 02:23:43
【问题描述】:

我正在为我的应用程序使用 Meteor 和 React。在我的应用程序中,我使用 account-ui、account-facebook 让用户能够使用 facebook 帐户登录。 现在,我想检查用户是否使用 facebook 登录或普通用户/密码登录。我查看了用户集合并看到了

1) if user used facebook to login, there is services.facebook in user collection
2) if user used regular user/pass to login, there is services.password  in users collection

在服务器中,我有方法返回登录服务(facebook 或密码)

Meteor.methods({
        getLoginService: function(){
            let services = Meteor.user().services;
            if (typeof services.facebook!=='undefined'){
                return 'facebook';
            }else if (typeof services.password!=='undefined'){
                return 'password';
            }
            return 'undefined';
        },
    });

在客户端,如果会检查是(facebook登录)还是(用户/密码登录),那么我可以相应地渲染屏幕

App.Components.Dashboard = React.createClass({

  render() {
    var lservice='';
    Meteor.call("getLoginService",function(error,service) {
      if (error){
      }else {
            lservice = service;
      }
    });

    if (lservice === 'facebook'){
        return (
            <div id="dashboard-content">
              <div className="row">
                <div className="col-lg-12">
                  <h1 className="page-header">Facebook connect</h1>
                  <p>put facebook information here</p>
                </div>
              </div>
            </div>
        );



    }else{
        return (
            <div id="dashboard-content">
              <div className="row">
                <div className="col-lg-12">
                  <h1 className="page-header">Facebook connect</h1>
                  <p>put facebook connect button here</p>
                </div>
              </div>
            </div>
        );
      }

  }
});

问题出在客户端。因为 Meteor.call 是异步的,所以 lservice 不会从回调函数中获取值。 我也尝试找到一种方法将html返回放入回调函数(错误,服务)但不成功。

你知道无论如何要解决这个问题。或者你有什么更好的办法来识别用户用来登录的服务(可能是帐户-facebook 的挂钩)

【问题讨论】:

    标签: javascript asynchronous meteor reactjs meteor-accounts


    【解决方案1】:

    首先将您对Meteor.call 的调用移至componentWillMount,以便它只运行一次——就在组件第一次渲染之前。

    render 方法中的代码将在每次 state 或 props 更改时调用,您可能只需要获取一次登录服务。

    接下来,不是将service 字符串存储在局部变量中,而是将其存储在state 中,以便组件在每次更新时呈现。

    getInitialState() {
      return {};
    },
    componentWillMount() {
      Meteor.call("getLoginService", (error, service) => {
        if(error) {
          // handle error
        } else {
          this.setState({ service });
        }
      });
    },
    render() {
      const { service } = this.state;
    
      if(service === 'facebook') {
        // return facebook view
      } else if(service === 'password') {
        // return password view
      } else {
        // return loading view
      }
    }
    

    您的应用程序第一次渲染时,服务可能不可用(它将等待请求返回),因此它将在 else 子句中渲染加载视图。

    但是,当调用回调时(前提是没有错误),组件的状态将被更新,组件将重新渲染。

    这一次服务将可用,并显示正确的视图。

    【讨论】:

    • 感谢丹普林斯。我会用你的代码看看。再次感谢您的快速回答
    • 您好,我尝试了您的代码,但返回错误:未捕获的类型错误:无法读取 null 的属性“服务”。如果我在 const {service} = this.state 之后放置 alert(service),我可以看到 service 的值是正确的,但错误仍然存​​在并且页面无法呈现..
    • @David,您需要从getInitialState 返回组件的初始状态,否则默认为null,您不能将null 解构为对象。更新了答案。
    • 我已经使用了你的代码并将alert() 放到每一行代码中进行调试。我可以看到:componentWillMount 将首先执行(但不完全-> Meteor.call 中的回调方法尚未触发)。然后 render() 被调用并且 'service' 得到 'undefined' 值-> 所以我不能使用 'service' 将它的值与 'facebook' 和 'password' 进行比较 --> render() 总是显示加载视图:失败。渲染()完成后。最后调用回调方法并且“服务”得到正确的值。但是此时,render() 已经被调用来显示“正在加载的视图”:这不是预期的
    • 在加载数据之前无法显示正确的视图。这将在第二次调用 render 时发生,此时 service 将具有正确的值。您可以渲染加载视图或返回 null 以在此之前不渲染任何组件。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-07
    • 2020-11-04
    • 1970-01-01
    相关资源
    最近更新 更多