简体   繁体   中英

Using async meteor.call() in meteor-react render() method

I am using Meteor and React for my app. in my app, i use account-ui, account-facebook to let user is able to sign in by using facebook account. Now, i want to check if user is using facebook to sign-in Or regular user/pass to sign-in. I look at users collection and see that

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

in server, i have method to return loginservice (facebook or password)

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

In client side, if will check to see if that is (facebook login) Or (User/pass login), then i can render the screen accordingly

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

  }
});

The problem is at client side. Because Meteor.call is async so that lservice will not get the value from callback function. I also try to find a way to put html return into callback function(error, service) but not successful.

Do you know anyway to solve this problem. Or do you have any better idea to recognize what service that user used to login (maybe a hook to account-facebook)

Start by moving your call to Meteor.call into componentWillMount so that it only runs once—just before the component is first rendered.

Code in your render method will be called each time that the state or props change and you probably only need to get the login service once.

Next, rather than storing the service string in a local variable, store it in state so that component renders each time it is updated.

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

The first time your application renders, the service probably won't be available (it'll be waiting for the request to come back), so it will render the loading view in the else clause.

However, when the callback is called (providing there are no errors), the state of the component will be updated and the component will re-render.

This time the service will be available and the correct view will be shown.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM