2017-05-16 66 views
2

我正在嘗試使用React-React-v4來渲染一些元素。React和React路由器,使用不同的道具渲染相同的元素兩次會導致兩個元素具有相同的道具?

構思是組件是來自網站的文章列表,每條路線使用不同的API密鑰從不同的網站獲取文章。

我正在使用單個組件來顯示文章,並且每條路線都要傳遞不同的API密鑰。

我遇到的問題是每個路由都使用相同的API密鑰,這是訪問的第一個Route的關鍵。

源代碼如下:

var APIKeys = { 
 
    BBCKey: 'https://newsapi.org/v1/articles?source=bbc-sport&sortBy=top&apiKey=2d64206e989a4d31b5572ee0ceedc4ee', 
 
    ESPNKey: 'https://newsapi.org/v1/articles?source=espn&sortBy=top&apiKey=2d64206e989a4d31b5572ee0ceedc4ee', 
 
    FourFourTwoKey: 'https://newsapi.org/v1/articles?source=four-four-two&sortBy=top&apiKey=2d64206e989a4d31b5572ee0ceedc4ee' 
 
} 
 

 
let App =() => (
 
    <BrowserRouter> 
 
     <div className="container"> 
 
     <header> 
 
     <span className="icn-logo"><i className="material-icons">code</i></span> 
 
     <ul className="main-nav"> 
 
      <li><NavLink exact to="/">Home</NavLink></li> 
 
      <li><NavLink to="/BBCSport">BBC Sport</NavLink></li> 
 
      <li><NavLink to="/FourFourTwo">FourFourTwo</NavLink></li> 
 
      <li><NavLink to="/ESPN">ESPN</NavLink></li> 
 
     </ul> 
 
     </header> 
 
     <Switch> 
 
     <Route exact path="/" component={Home} /> 
 
     <Route path="/BBCSport" render={() => <GetArticles APIKey={APIKeys.BBCKey} /> } /> 
 
     <Route path="/FourFourTwo" render={() => <GetArticles APIKey={APIKeys.FourFourTwoKey} /> } /> 
 
     <Route path="/ESPN" render={() => <GetArticles APIKey={APIKeys.ESPNKey} /> } /> 
 
     <Route component={NotFound} /> 
 
     </Switch> 
 
     </div> 
 
    </BrowserRouter> 
 
); 
 

 
export default App;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

import React, { Component } from 'react'; 
 
import axios from 'axios'; 
 
import ArticleList from './ArticleList'; 
 

 
export default class GetArticles extends Component { 
 

 
    constructor(props) { 
 
    super(props); 
 
    this.state = { 
 
     articleTitles: [], 
 
     loading: true 
 
    }; 
 
    } 
 

 
    componentDidMount() { 
 
    axios.get(this.props.APIKey) 
 
     .then(response => { 
 
     let titles = response.data.articles.map((currentObj) => { 
 
      return currentObj.title; 
 
     }); 
 

 
     this.setState({ 
 
      articleTitles: titles, 
 
      loading: false 
 
     }); 
 
     }) 
 
     .catch(error => { 
 
     console.log('Error fetching and parsing data', error); 
 
     }); 
 
    } 
 

 
    render() { 
 
    return (
 
     <div> 
 
     <div className="main-content"> 
 
      <h1 className="main-title">Articles</h1> 
 
      { (this.state.loading) ? <p>Loading</p> : <ArticleList list={this.state.articleTitles} /> } 
 
     </div> 
 
     </div> 
 
    ); 
 
    } 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

我的兩個問題是,這是使用這樣的單組分一個好主意,甚至如果它呈現不同的信息,或者我應該有一個呈現每個di的組件不同的文章列表?

我該如何解決這個問題,以便使用合適的API密鑰?

回答

1

我認爲原因是,componentDidMount只會在初始渲染後被調用,因爲每個路由使用相同的組件,所以componentDidMount將不會再被調用。您還需要使用componentwillreceiveprops生命週期方法,並檢查是否收到新的APIkey,然後在其中執行api調用。

componentDidMount:

componentDidMount()後的成分是 安裝被立即調用。需要DOM節點的初始化應該放在這裏。如果 需要從遠程端點加載數據,則這是 實例化網絡請求的好地方。在此方法中設置狀態將會觸發重新渲染。

componentWillReceiveProps

componentWillReceiveProps()一個安裝部件 接收新道具之前被調用。如果您需要更新狀態以響應prop更改(例如,重置它),您可以比較this.props 和nextProps,並使用this.setState()以 此方法執行狀態轉換。

編寫組件是這樣的:

export default class GetArticles extends Component { 

    constructor(props) { 
    super(props); 
    this.state = { 
     articleTitles: [], 
     loading: true 
    }; 
    } 

    componentDidMount() { 
    console.log('initial rendering', this.props.APIKey) 
    this._callApi(this.props.APIKey); 
    } 

    componentWillReceiveProps(newProps){ 
    if(newProps.APIKey != this.props.APIKey){ 
     this._callApi(newProps.APIKey); 
     console.log('second time rendering', newProps.APIKey) 
    } 
    } 

    _callApi(APIKey){ 
    axios.get(APIKey) 
     .then(response => { 
     let titles = response.data.articles.map((currentObj) => { 
      return currentObj.title; 
     }); 

     this.setState({ 
      articleTitles: titles, 
      loading: false 
     }); 
     }) 
     .catch(error => { 
     console.log('Error fetching and parsing data', error); 
     }); 
    } 

    render() { 
    return (
     <div> 
     <div className="main-content"> 
      <h1 className="main-title">Articles</h1> 
      { (this.state.loading) ? <p>Loading</p> : <ArticleList list={this.state.articleTitles} /> } 
     </div> 
     </div> 
    ); 
    } 
} 
+0

我認爲這會是這樣做的生命週期方法,但是這並不能解決問題,我會繼續玩耍。 – tomhughes

+0

做一件事,把'console.log(this.props。APIKey)'內部渲染方法,並顯示更改路由時的結果。 –

+0

也將'console.log()'放在'componentDidMount'和'componentWillRecieveProps'方法中,並檢查它們是否正在進行路由更改。 –

相關問題