2015-10-26 52 views
0

我正試圖找到讓我的應用程序和組件依賴於我所做的單個ajax調用的最佳方式。我的應用程序通過第三方進行身份驗證,並真正向用戶顯示任何有意義的信息,我必須使用其登錄信息,然後再調用其他服務以獲取有關它們的詳細信息。我從一對夫婦的事例制定,至今有這個如何使組件/應用程序等待Ajax調用

//auth.js 
module.exports = { 
    login(cb) { 
    if (this.user) { 
     if (cb) cb(true) 
     this.onChange(true) 
     return; 
    } 
    //if we don't have info about the user we call the other service here 
    request((res) => { 
     if (res) { 
     this.user = res 
     if (cb) cb(true) 
     this.onChange(true) 
     } else { 
     if (cb) cb(false) 
     this.onChange(false) 
     } 
    }) 
    }, 

    getUser() { 
    return this.user 
    }, 

    logout(cb) { 
    delete this.user 
    if (cb) cb() 
    this.onChange(false) 
    }, 

    loggedIn() { 
    return !!this.user 
    }, 

    onChange() {} 
} 

然後在我的組件我做的這一切在這似乎並不像一個大格局的地方。

import React from 'react'; 
import ReactDOM from 'react-dom'; 
import auth from './auth' 

export class ProductList extends React.Component{ 

    constructor(props) { 
     super(props); 
     //subscribe to on change event from the auth class 
     auth.onChange = this.updateAuth.bind(this) 
     this.state = {results: []}; 
    } 

    componentWillMount() { 
    //call login. if already logged in this method just returns the current user 
    auth.login(); 
    } 

    getProducts() { 
    if(this.state.loggedIn) { 
     $.get(config.server.url + "/api/User/" + auth.getUser().Id + "/Products", function(result) { 
     this.setState({ 
      results: result.data.products 
     }); 
     }.bind(this)); 
    } 
    } 

    updateAuth(loggedIn) { 
    this.setState({ 
     loggedIn: loggedIn 
    }); 
    this.getProducts() 
    } 

    componentDidMount() { 
    this.getProducts() 
    } 

    render() { 
    return (
     <table> 
     <tbody> 
      {this.state.results.map(function(result) { 
       return <ProductItem key={result.Id} data={result}/>; 
      })} 
     </tbody> 
     </table> 
    ) 
    } 
}; 

ReactDOM.render(
    (<ProductList/>), 
    document.getElementById('react-forms') 
); 

所以我基本上只是掛鉤的事件處理程序中的每一個反應成分我已經和檢查所有的地方相同的屬性和它只是似乎很脆弱。我想我正在尋找一種方法來告訴我'應用程序',我正在等待事情發生在我的組件有效之前。

+2

它很難說出你的組件結構是什麼樣子,但是你有沒有考慮在頂級組件中做ajax調用,然後將一個'auth' prop傳遞給子組件,它會根據這個值顯示數據那道具? – Mark

+0

@Mark我給我的例子增加了一些。現在我已經有了一個非常天真的設置,因爲我現在沒有使用任何類似redux或react-router的東西。只是試圖替換我在淘汰賽中的一些組件。我喜歡製作頂級組件的想法,但我對React有點新,並且不太瞭解實現這一目標的最佳方法。我看到複合組件和類似的東西,但我不太確定如何擴展或包裝組件。任何例子都會很棒。 – ThrowsException

回答

0

我建議你按照反應教程(https://facebook.github.io/react/docs/tutorial.html#fetching-from-the-server)中概述的結構。 ajax調用是使用jquery ajax函數從頂層組件CommentBox製作的,然後通過道具傳遞給其他組件CommentListCommentForm。以下代碼直接來自教程。由於使用es6,語法略有不同,但概念保持不變。

var CommentBox = React.createClass({ 
    loadCommentsFromServer: function() { 
    $.ajax({ 
     url: this.props.url, 
     dataType: 'json', 
     cache: false, 
     success: function(data) { 
     this.setState({data: data}); 
     }.bind(this), 
     error: function(xhr, status, err) { 
     console.error(this.props.url, status, err.toString()); 
     }.bind(this) 
    }); 
    }, 
    getInitialState: function() { 
    return {data: []}; 
    }, 
    componentDidMount: function() { 
    this.loadCommentsFromServer(); 
    setInterval(this.loadCommentsFromServer, this.props.pollInterval); 
    }, 
    render: function() { 
    return (
     <div className="commentBox"> 
     <h1>Comments</h1> 
     <CommentList data={this.state.data} /> 
     <CommentForm /> 
     </div> 
    ); 
    } 
});