2016-09-18 9 views
5

私は反応成分中のMeteor.user()サブスクリプションを待つ方法を理解するのに苦労しています。 Meteor.userId()_idを返しますが、電子メールアドレスにアクセスしようとすると、Meteor.user()は未定義を返すため、ユーザーがログインしていることがわかります。私はそれがまだ利用できないので仮定します。Meteor/React - Meteor.user()を待つ方法

Meteor.user()は私が手動で購読している出版物ではないので、Reactコンポーネントでそれを待つ方法がわかりません。誰かが私を例にして指すことができますか?

import { Meteor } from 'meteor/meteor'; 
import React from 'react'; 
import { Link } from 'react-router'; 
import { createContainer } from 'meteor/react-meteor-data'; 

import './BaseLayout.scss'; 


class BaseLayout extends React.Component { 

    constructor(props) { 
     super(props); 

     this.state = { 
      isAuthenticated: (Meteor.userId() !== null) ? true : false, 
     } 
    } 

    componentWillMount() { 
     if (!this.state.isAuthenticated) { 
      this.context.router.push('/login'); 
     } 
    } 

    componentDidUpdate(prevProps, prevState) { 
     if (!this.state.isAuthenticated) { 
      this.context.router.push('/login'); 
     } 
    } 

    toggleUserMenu() { 
     this.refs.userMenu.style.display = (this.refs.userMenu.style.display === 'block') ? 'none' : 'block'; 
    } 

    logout(e) { 
     e.preventDefault(); 
     Meteor.logout(); 
     this.context.router.push('/login'); 
    } 

    render() { 
     return(
      <div id="base"> 
       <div id="header"> 
        <div id="top-bar" className="clear-fix"> 
         <div className="float-left" id="logo"></div> 
         <div className="float-right" id="user-menu"> 
          <div onClick={this.toggleUserMenu.bind(this)}> 
           <span>{this.props.currentUser.emails[0].address}</span> 
           <div className="arrow-down"></div> 
          </div> 
          <div id="user-menu-content" ref="userMenu"> 
           <a onClick={this.logout.bind(this)}>Sign Out</a> 
          </div> 
         </div> 
        </div> 
       </div> 
       <div id="bodyContainer"> 
        {this.props.children} 
       </div> 
       <div id="footer"> 
        <ul> 
         <li><a href="mailto:[email protected]">Made by Us</a></li> 
        </ul> 
       </div> 
      </div> 
     ) 
    } 
} 
BaseLayout.contextTypes = { 
    router: React.PropTypes.object.isRequired, 
} 


export default BaseLayoutContainer = createContainer(() => { 

    var handle = Meteor.subscribe("user.classrooms"); 

    return { 
     currentUser: Meteor.user(), 
     dataLoading: !handle.ready(), 
     classrooms: Classrooms.find({}).fetch(), 
    }; 
}, BaseLayout); 

答えて

4

あなたはまた

currentUser ? true : flase 

整理コンポーネントを維持するための大きなヒントを三項演算を使用することができますconst { currentUser } = this.props;を行うことができます代わりにconst currentUser = this.props.currentUserを行うのに常にdestructure例えばです見てください:

render() { 
const { currentUser, children } = this.props; 
    return (
    <div id="base"> 
    <div id="header"> 
     <div id="top-bar" className="clear-fix"> 
     <div className="float-left" id="logo"></div> 
     <div className="float-right" id="user-menu"> 
      <div onClick={this.toggleUserMenu.bind(this)}> 
      {currentUser ? 
      <span>{currentUser.emails[0].address}</span> : 
      <span>Loading...</span> 
      } 
      <div className="arrow-down"></div> 
      </div> 
      <div id="user-menu-content" ref="userMenu"> 
      <a onClick={this.logout.bind(this)}>Sign Out</a> 
      </div> 
     </div> 
     </div> 
    </div> 
    <div id="bodyContainer"> 
     {children} 
    </div> 
    <div id="footer"> 
     <ul> 
     <li><a href="mailto:[email protected]">Made by Us</a></li> 
     </ul> 
    </div> 
    </div> 
) 
} 
+0

答えが明白なときに私はそれを愛する、私はそれを見たと思うだけ!消滅についてのヒントをありがとう、私はそれがマークアップをよりクリーンでより依存しないように保つ方法を見ることができます。再度、感謝します! – Scott

+0

私は@DMXを助けることができてうれしいありがとう! –

1

dataLoadingを追加:!handle.ready()|| !Meteor.user()をcreateContainerに追加します。

export default BaseLayoutContainer = createContainer(() => { 

    var handle = Meteor.subscribe("user.classrooms"); 

    return { 
    currentUser: Meteor.user(), 
    dataLoading: !handle.ready() || !Meteor.user(), 
    classrooms: Classrooms.find({}).fetch(), 
    }; 
}, BaseLayout); 

Meteor.user()は、あなたがそのようなdataLoading ? "" : Meteor.user()などの条件を追加することによって、呼び出している防ぐことを確認しますので、ロードする前に、コンポーネント内に定義されません。

ユーザーが!!Meteor.user()でログインしているかどうかを確認することもできます。通常Meteor.userId()の方が読み込みが高速ですが、電子メールなどのユーザーのデータにアクセスする必要がある場合は、Meteor.user()に電話する必要があります。

1

回答は良いですが、しばらくしてから、多くのコンポーネントでこれを何度も繰り返す必要があることに気づくでしょう。あるいは、Accounts.loginServicesConfigured()が真であることを確認してから、最上位コンポーネントのレンダリングをTrackerで実行することもできます。メテオのドキュメントを引用する: "Accounts.loginServicesConfigured()関数は、ログインサービスが設定されるとtrueを返す無効なデータソースです"。私は流星を使用して、反応し、還元し、ルータに反応しています。

import React, { Component } from 'react'; 
import { Accounts } from 'meteor/accounts-base'; 
import { Route, Switch } from 'react-router-dom'; 
import { Tracker } from 'meteor/tracker'; 

class App extends Component { 
    constructor(props) { 
    super(props); 

    this.state = { loading: true }; 
    } 

    componentWillMount() { 
    Tracker.autorun(() => { 
     if (Accounts.loginServicesConfigured()) { 
     this.setState({ loading: false }); 
     } 
    }); 
    } 

    render() { 
    return (
     <div className="app"> 
     { 
      this.state.loading ? (<Spinner />) : (
      <Route exact path="/" component={HomePage} /> 
     ) 
     } 
     </div> 
    ); 
    } 
} 

うまくいけば、この代替方法は他の人の手助けになると思います。がんばろう!

関連する問題