2016-09-14 2 views
1

탭이있는 구성 요소가 URL을 변경하고 페이지에 머물러있어 구성 요소를 자식으로 렌더링하게하는 중첩 경로가 여러 개있는 문제가 발생했습니다 . 이것은 잘 작동합니다.데이터를 가져 오기 전에 React-Router 탭 구성 요소 장착

URL 경로를 탭으로 사용하는 이유는 앱의 다른 곳에서 sales/:id/notes을 클릭하면 올바른 탭으로 직접 이동하기 때문입니다.

문제는 상위 경로에있는 componentDidMount 함수의 모든 데이터를 가져 오는 것입니다. 그래서 SalesShowPage이 마운트되면 요청을합니다. SalesShowPage으로 직접 이동 한 다음 NotesTab을 클릭하면 모든 데이터가로드 요청 이후 완벽하게로드됩니다. 우리가 sales/:id/notes에 직접 가면 내가이 늘 NotesTab가 있기 때문에 장착 후까지 호출되는 상태에서 isFetching 플래그를 설정하려고하면 NotesTabrendercomponentDidMount 방법 SalesShowPage 전에 호출되는 하위 구성 요소이므로

문제가 발생합니다 부모 컴포넌트로부터 요청 액션을 만든다.

모든 노트를 반복 할 때 노트에 대해 정의되지 않은 오류가 발생합니다.

반응 라우터가있는 중첩 경로의 부모로부터 데이터를 가져 오는 더 좋은 방법이 있습니까?

루트 구성 요소의 렌더링을 지연하거나 데이터가 실제로 부모로부터 인출 될 때로드 메시지를 표시 할 수 있습니까? 임의로 isFetching 플래그를 componentWillMount에서 설정하고 데이터 가져 오기 및 가짜로드 아이콘을 표시하고 싶지 않습니다.

해당 구성 요소가 마운트 될 때 모든 메모를 요청할 수 있지만 API 끝점을 변경하고 다른 경로를 추가해야합니다. 현재 끝점을 사용하는 대신

아래 코드는 이해하기 쉽게 단순화 된 코드입니다.

아래에 표현한 {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()에서, 데이터 전에 장착 것을 가져 오는 시작 : 나는 두 갈래의 접근 방식을 권하고 싶습니다 showTabstrue입니다 Tabs 경우

SalesShowPage.defaultProps = { 
    showTabs: false 
}; 

그럼 당신은 당신이 requ에 대한 성공 액션을 설정할 수있는 렌더링 할 수 있습니다 그래서 당신은 대체가 필요합니다 동부 표준시. 탭이 준비가 될 때까지 당신이 전체 UI를 숨기려면

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

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

대신 로딩 화면을 보여 isFetching를 사용할 수 있습니다.

관련 문제