2016-09-14 5 views
1

は私がURLを変更します理想的なタブをクリックするタブ付き部品を作るために複数のネストされたルートを持って問題に遭遇しているフェッチされるルータは、反応し、子供などのコンポーネントをレンダリング。これはうまく動作します。ページに滞在、タブデータの前に実装部品が

URLルートをタブとして使用する理由は、アプリ内の別の場所でユーザーがsales/:id/notesをクリックすると、正しいタブに直接移動するためです。

問題は、私が親ルートでcomponentDidMount機能からすべてのデータを取得していますということです。したがって、SalesShowPageがマウントされると、要求が行われます。 SalesShowPageに直接アクセスしてNotesTabをクリックすると、ロード時にすべてのデータが完全にロードされます。我々はsales/:id/notesに直接行けば、私はそれは文句を言わないNotesTabがあるために取り付けられた後まで呼び出さ状態でisFetchingフラグを設定しようとNotesTabはそのrendercomponentDidMount方法はSalesShowPage前に呼び出される子コンポーネントであるため

問題が起こります親コンポーネントから要求アクションを作成します。

すべての音符をループすると、ノートには未定義のエラーがスローされます。

反応ルータでネストされたルートの親からのデータフェッチを処理するより良い方法はありますか?

ルートコンポーネントのレンダリングを遅らせたり、データが実際に親からフェッチされたときに読み込みメッセージを表示できますか?私は任意にisFetchingフラグをcomponentWillMountから設定したいとは思わないし、データがフェッチされ、偽の読み込みアイコンが表示されています。

私は、すべてのノートを要求する場合、そのコンポーネントがマウント作ることができるが、それはAPIエンドポイントを変更し、別のルートを追加することが必要となります。現在のエンドポイントを使用する代わりに。

以下のコードは、理解しやすくするための簡略化されたバージョンです。

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

以下のアクションが真の作品にisFetchingフラグを設定SalesShowPage componentDidMount方法からサーバへの要求のレプリカです。指定されたタブコンポーネントがレンダリングされてエラーが発生した後に実行されます。

//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() { 
    this.props.fetchSales(this.props.saleId); 
} 

をしかし、それは非同期アクションだから、それはまだ時間で終了する可能性は低いです:、

まずcomponentWillMount()で、データが前実装することをフェッチ開始:私は2つのアプローチをお勧めしますshowTabstrueあるTabs場合

SalesShowPage.defaultProps = { 
    showTabs: false 
}; 

次に、あなたがのrequの成功アクションに設定することができ、レンダリングすることができますので、あなたは、フォールバックを必要としますEST(東部基準時。

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を使用することができます。

関連する問題