2

我正在創建一個主 - 細節導航,就像這裏的示例the react router example;React Router master-detail:在刷新頁面之前,children組件不會呈現新視圖

我有一個容器組件OneCheckpointContainer,這使得導航面板CheckpointNav(鏈接),和數據分量OneCheckpointData(根據負荷這個人去抓取數據,並呈現OneCheckpointView

當我點擊鏈接中的一個在CheckpointNav中除瀏覽器中的URL發生變化外,沒有任何事情發生,直到我刷新頁面以獲取新數據,然後在子視圖中呈現一個新組件(也沒有錯誤)

I我不確定這個bug是否是因爲子組件也負責提取數據以及vie W上。

這裏是我有路線設置:

<Route path="/modules/:id" component={OneCheckpointContainer}> 
    <Route path="/modules/:id/checkpoints/:cp_id" component={OneCheckpointData} /> 
    </Route> 

OneCheckpointContainer

import React from 'react'; 
import CheckpointNav from './CheckpointNav'; 

class OneCheckpointContainer extends React.Component { 
    constructor(props, context) { 
    super(props, context); 

    this.state = { 
     checkpoints: null, 
     user: null 
    }; 

    } 

    componentWillMount() { 
    this.loadCheckpoints(); 
    this.context.getUser((data) => this.setState({ user: data })); 
    } 

    loadCheckpoints() { 
    $.ajax({ 
     url: `/api/v1/modules/student/${this.props.params.id}/checkpoints`, 
     method: 'GET', 
    }).done((data) => { 
     this.setState({ checkpoints: data }); 
    }); 
    } 

    render() { 
    return (
     <div> 
     <div className="col-xs-3"> 
      <CheckpointNav mid={this.props.params.id} checkpoints={this.state.checkpoints} /> 
     </div> 
     <div className="col-xs-9"> 
      { this.props.children || <div>No Children Yet</div>} 
     </div> 
     </div> 
    ) 
    } 
} 

OneCheckpointContainer.displayName = OneCheckpointContainer; 

OneCheckpointContainer.contextTypes = { 
    getUser: React.PropTypes.func.isRequired 
}; 

export default OneCheckpointContainer; 

這裏是CheckpointNav雖然我不相信錯誤是在這裏:

import React from 'react'; 
import NavLink from '../widgets/NavLink'; 

const CheckpointNav = (props) => { 
    const checkpointList = props.checkpoints && props.checkpoints.length > 0 ? 
    props.checkpoints.map((item) => { 
     return <li key={item.cp._id} className="list-group-item"> 
     <NavLink className="nav-link" to={"/modules/" + props.mid + "/checkpoints/" + item.cp._id}> 
     { item.cp.title}</NavLink></li> 
    }) : <div>No CPS</div>; 
    return (
    <div className="card one-module-card"> 
     <div className="card-block modules-card-body"> 
     <ul className="list-group tags-group"> 
      { checkpointList } 
      <li className="list-group-item new-cp"><NavLink className="" 
      to={'/post/checkpoint/' + props.mid} 
      > 
      New Checkpoint 
      </NavLink></li> 
     </ul> 
     </div> 
    </div> 
); 

}; 

export default CheckpointNav; 

OneCheckpointData 沒有獲取新的數據並呈現新的,除非我刷新

import React from 'react'; 
import CheckpointView from './CheckpointView'; 

class OneCheckpointData extends React.Component { 
    constructor(props, context) { 
    super(props, context); 

    this.state = { 
     checkpoint: null, 
     user: null 
    }; 

    } 

    componentWillMount() { 
    this.loadCheckpoint(); 
    this.context.getUser((data) => this.setState({ user: data })); 
    } 

    loadCheckpoint() { 
    $.ajax({ 
     url: `/api/v1/modules/three/cp/${this.props.params.cp_id}`, 
     method: 'GET', 
    }).done((data) => { 
     this.setState({ checkpoint: data }); 
    }); 
    } 

    render() { 
    return this.state.checkpoint ? <CheckpointView user={this.state.user} checkpoint={this.state.checkpoint} /> : null; 
    } 
} 

OneCheckpointData.displayName = OneCheckpointData; 

OneCheckpointData.contextTypes = { 
    getUser: React.PropTypes.func.isRequired 
}; 

export default OneCheckpointData; 

**我已經離開了OneCheckpointView因爲它應該是irrelavant **

回答

5

在,這種情況下,你可以得到的道具爲loadCheckpoing(props)函數的參數,你可以把在componentWillReceiveProps的新道具,就像下面

componentWillMount(this.props) { 
    this.loadCheckpoint(this.props); 
} 

componentWillReceiveProps(nextprops) { 
    this.loadCheckpoint(nextprops); 
} 

loadCheckpoint(props) { 
    this.context.getUser((data) => this.setState({ user: data })); 
    $.ajax({ 
    url: `/api/v1/modules/three/cp/${props.params.cp_id}`, //please check i have replace the this.props to props as we have props as a parameter 
    method: 'GET', 
    }).done((data) => { 
    this.setState({ checkpoint: data }); 
    }); 
} 

,我會更喜歡使用react- redux或迴流庫來處理您的ajax數據查詢,但我提議的解決方案應該爲您完成這項工作。

+0

我想我明白你要做什麼,但是你不能將this.props作爲參數傳遞給componentWillMount – fresh5447

1

的問題是,您的組件僅在安裝前獲取數據。這隻在第一次顯示時才起作用。這些組件每當他們收到新的屬性時也需要獲取他們的數據,例如導航到新位置後,從路由器獲取ID。

爲了做到這一點,最簡單的方法是添加一個componentWillReceiveProps,將以前的道具與新道具進行比較,並根據需要提取新數據。

另一種方法是在路由配置中添加一個onEnter處理程序,以在路由發生更改時獲取數據。

查看this question's answers查看兩種方法的示例。

1

我想這是因爲你已經調用了componentwillMount中的函數loadcheckpoints。這僅在組件生命週期中被調用一次。 由於單擊導航欄中的鏈接時組件已裝載,因此不會調用compoenntwillmount。因此,不會發生數據提取。

我想你應該嘗試下面的方法。 CheckpointNav中的鏈接的onclick函數應該從OneCheckpointContainer傳遞。 loadeddata應該設置爲在容器中的狀態,它將以道具的形式將數據傳遞給OneCheckpointData。

1

兩個步驟來診斷:

  1. 檢查是否你的方法,當你點擊不同的鏈接loadCheckpoint被稱爲每次。只要留下這樣一行console.log(new Date().toLocaleTimeString())該方法

  2. 如果步驟1成功,然後檢查是否有這部分this參考問題: (data) => { this.setState({ checkpoint: data }); }

順便說一句,你最好把AJAX請撥打componentDidMount方法。請參閱:https://facebook.github.io/react/docs/component-specs.html#mounting-componentdidmount