2016-09-14 56 views
1

我遇到了一個問題,我有多個嵌套的路由,使標籤組件理想地點擊選項卡將更改URL,留在頁面上並呈現組件作爲子組件。這工作得很好。React-Router選項卡組件數據提取之前的組件安裝

將url路徑作爲製表符使用的原因是,如果應用程序中的某個用戶單擊了sales/:id/notes,它將直接轉到正確的製表符。

問題是我從父路由中的componentDidMount函數中獲取所有數據。所以當SalesShowPage掛載它發出請求。如果我直接轉到SalesShowPage,然後點擊NotesTab,所有數據都會在載入請求時完美加載。

問題發生,如果我們直接去sales/:id/notes,因爲NotesTab是一個子組件的rendercomponentDidMount方法被SalesShowPage之前調用,如果我嘗試設置isFetching標誌狀態時,它不會被調用後才NotesTab已安裝,因爲它從父組件發出請求操作。

在循環所有音符時,這會爲音符引發未定義的錯誤。

有沒有一種更好的方法來處理從具有react-router的嵌套路由的父節點獲取數據?

當數據實際從父級獲取時,能否延遲路由組件的渲染或顯示加載消息?我不想從componentWillMount任意設置isFetching標誌,然後數據提取並顯示一個假加載圖標。

我可以在組件掛載時提出請求,但需要更改端點並添加其他路由。而不是使用當前的終點。

下面的代碼是一個簡化版本,以便於理解。

// Routes.js 
<Route path="/sales/:id" component={SalesShowPage} > 
    <Route path="contacts" component={ContactsTab}/> 
    <Route path="notes" component={NotesTab}/> 
    <Route path="emails" component={EmailsTab}/> 
</Route> 

呈現的{props.children}是來自上述路線的組件。

//Tabs.js 
const Tabs = (props) => { 
    return (
    <div className='tabsContainer'> 
     <TabsHeader> 
      <Link to='sales/:id/contacts'>Contacts</Link> 
      <Link to='sales/:id/notes'>Notes</Link> 
      <Link to='sales/:id/emails'>Emails</Link> 
     </TabsHeader> 
     <TabsContent className='tabContent'> 
     {props.children} 
     </TabsContent> 
    </div> 
); 
}; 

這是獲取呈現並獲取所有選項卡數據的主要組件。並非所有選項卡都具有在此組件上加載的數據,某些選項卡會自行請求數據。例如電子郵件標籤,由於查詢大小以及查看標籤的頻率,它不會查詢初始頁面加載時的所有電子郵件。

//SaleShowPage 

class SalesShowPage extends React.Component { 
    constructor (props) { 
    super(props); 
    } 
    componentDidMount() { 
    this.props.fetchSales(this.props.saleId); 
    } 
    render() { 
    return (
     <div className={styles.flex}> 
      <SalesDetails sale={this.props.sale}/> 
      <Tabs {...this.props}/> 
     </div> 
    ); 
    } 
} 

const mapStateToProps = (state, props) => { 
    return { 
    saleId: props.params.id, 
    sale: state.sales[props.params.id], 
    }; 
}; 

const mapDispatchToProps = (dispatch) => ({ 
    fetchSale: (id) => dispatch(fetchSale(id)) 
}); 

export default connect(mapStateToProps, mapDispatchToProps)(SalesShowPage); 

的下面動作是請求從SalesShowPage componentDidMount方法isFetching標誌設置爲真作品的服務器的一個副本。但是在我們指定的Tab組件被渲染後得到執行導致出錯。

//SalesShowAction.js 

export function fetchSale (id) { 
    return dispatch => { 
    dispatch({type: actions.FETCH_SALE_REQUEST, isFetching: true}); 
    return API.get(`/sales/${id}`).then(json => dispatch(receiveSale(json))); 
    }; 
} 

回答

1

你取一旦部件已經安裝,這意味着它會呈現出你需要獲取的,而你仍然收到這個數據數據的選項卡。我建議採取雙管齊下的方法:

首先,開始獲取該安裝數據之前,在componentWillMount()

componentWillMount() { 
    this.props.fetchSales(this.props.saleId); 
} 

但因爲它是一個異步操作,它仍然是不太可能的時間來完成,所以你需要一個備用:

SalesShowPage.defaultProps = { 
    showTabs: false 
}; 

然後你就可以渲染Tabs如果showTabstrue,您可以在爲熱曲的成功操作設置美東時間。

renderTabs() { 
    if(this.props.showTabs) { 
    return <Tabs {...this.props}/>; 
    } 
} 

render() { 
    return (
    <div className={styles.flex}> 
      <SalesDetails sale={this.props.sale}/> 
      {this.renderTabs()} 
    </div> 
); 
} 

如果你想隱藏整個UI,直到標籤準備好了,你可以使用isFetching顯示加載屏幕來代替。

相關問題