React和React Router,使用不同的prop两次渲染相同的元素会导致两个具有相同prop的元素? [英] React and React Router, rendering the same element twice with a different prop results in two elements with the same prop?

查看:68
本文介绍了React和React Router,使用不同的prop两次渲染相同的元素会导致两个具有相同prop的元素?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将React与React-router v4一起使用以渲染一些元素.

I'm trying to use React with React-router v4 to render a few elements.

这个想法是,该组件是网站上的文章列表,每个Route使用不同的API密钥来从其他网站上获取文章.

The idea is that the component is a list of articles from a website, with each Route using a different API key to get articles from a different site.

我正在使用单个组件来显示文章,并且对于每个路径,我都希望传递不同的API密钥.

I'm using a single component to display the articles, and with each Route I want to pass a different API key.

我遇到的问题是,每个路由都使用相同的API密钥,这是访问的第一个路由的密钥.

The issue I have is that each route is using the same API key, which is the key of the first Route visited.

源代码如下:

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

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>

我的两个问题是,即使这样呈现单个信息,使用这样的单个组件还是一个好主意?还是我应该拥有一个呈现每个不同文章列表的组件?

My two questions are, is this a good idea using a single component like this, even if it is rendering different information, or should I have a component that renders each different list of articles?

如何解决它,以便使用适当的API密钥?

How can I fix it so the appropriate API key is used?

推荐答案

我认为原因是,componentDidMount将仅在初始渲染之后被调用ocne,因为您为每条路线使用了相同的组件,因此componentDidMount将不会再被呼叫.您还需要使用componentwillreceiveprops生命周期方法,并检查是否收到新的APIkey,然后在其中进行api调用.

I think reason is, componentDidMount will get called only ocne, just after the initial rendering, since you are using the same component for each route, so componentDidMount will not get called again. You need to use componentwillreceiveprops lifecycle method also, and check if you receive the new APIkey then do the api call inside that.

componentDidMount:

componentDidMount:

componentDidMount()在组件被调用后立即被调用 已安装.需要DOM节点的初始化应在此处进行.如果你 需要从远程端点加载数据,这是一个很好的地方 实例化网络请求.在此方法中设置状态将 触发重新渲染.

componentDidMount() is invoked immediately after a component is mounted. Initialization that requires DOM nodes should go here. If you need to load data from a remote endpoint, this is a good place to instantiate the network request. Setting state in this method will trigger a re-rendering.

componentWillReceiveProps :

componentWillReceiveProps:

在安装的组件之前调用

componentWillReceiveProps() 收到新的道具.如果您需要更新状态以响应 属性更改(例如,重置它),您可以对此进行比较. 和nextProps并使用this.setState()执行状态转换 这种方法.

componentWillReceiveProps() is invoked before a mounted component receives new props. If you need to update the state in response to prop changes (for example, to reset it), you may compare this.props and nextProps and perform state transitions using this.setState() in this method.

这样编写组件:

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

这篇关于React和React Router,使用不同的prop两次渲染相同的元素会导致两个具有相同prop的元素?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆