当父组件的状态更新时,React Child组件不会更新

时间:2018-04-28 11:05:24

标签: reactjs google-maps google-maps-api-3 components

我正在使用Google地方搜索API。当我从Google Place搜索API获取一些数据时,它只返回20条记录并提供下一页标记以获得更多结果,然后我抓住每个地方的place_id然后再次获取该地点的所有详细信息,这样我就是我所做的两次获取数据创建了两个组件,一个负责获取位置,它是我的父组件,另一个负责使用import React, { Component } from 'react'; import Search from './Components/Search'; import Display from './Components/Display'; import Header from './Components/Header'; import Instructions from './Components/Instructions'; const URI = 'https://maps.googleapis.com/maps/api/place/textsearch/json?query='; const placeURI = 'https://maps.googleapis.com/maps/api/place/details/json?placeid='; const API = '&key=xxxxxxxxxxxxxxxxxxxxxxxxx'; class Extractor extends Component { getData = (keyword, location, country) => { let dataURI = `${URI}${keyword}+${location}+${country}${API}`; let proxyUrl = 'https://cors-anywhere.herokuapp.com/', targetUrl = dataURI fetch(proxyUrl + targetUrl) .then((res) => res.json()) .then((data) => { let jsonData = JSON.parse(JSON.stringify(data)); let nextPageToken = jsonData.next_page_token; this.setState({nextPage: nextPageToken, googleData: jsonData, dataURI }); //console.log(dataURI"); }) .catch((e)=> console.log(`Error! ${e.message}`)); } isEmpty = (obj) => { for(var key in obj) { if(obj.hasOwnProperty(key)) return false; } return true; } viewMore = () => { let dataURI = `${this.state.dataURI}&pagetoken=${this.state.nextPage}`; let proxyUrl = 'https://cors-anywhere.herokuapp.com/', targetUrl = dataURI fetch(proxyUrl + targetUrl) .then((res) => res.json()) .then((data) => { let jsonData = JSON.parse(JSON.stringify(data)); let nextPageToken = jsonData.next_page_token; this.setState({nextPage: nextPageToken, googleData: jsonData, dataURI }); //console.log(dataURI"); }) .catch((e)=> console.log(`Error! ${e.message}`)); } constructor(props){ super(props); this.state = { googleData: [], nextPage: '', dataURI: '' } } render() { let displayData; if(this.state.googleData.status === 'OK'){ displayData = <Display googleData={this.state.googleData} nextPageToken = {this.state.nextPage} api={API} placeURI = {placeURI} viewMore = {this.viewMore} /> } else{ displayData = <Instructions /> } //console.log(this.state.dataURI); return ( <div> <Header /> <section> <Search getData={this.getData} /> {displayData} </section> </div> ); } } export default Extractor; 获取位置详细信息,它是我的子组件。这是我的代码

1。 Extractor.js(父组件

import React, { Component } from 'react';
import {
    Table,
    ProgressBar,
    Button
}
from 'react-bootstrap';

class Display extends Component {
    constructor(props) {
      super(props);
      this.state={
          rows: []
      }
    }

    componentDidMount(){
        var records = this.props.googleData;
        const API = this.props.api;
        const placeURI = this.props.placeURI;
        for (let p_id of records.results) {
            let dataURI = `${placeURI}${p_id.place_id}${API}`;
            let proxyUrl = 'https://cors-anywhere.herokuapp.com/',
                targetUrl = dataURI
            fetch(proxyUrl + targetUrl)
            .then((res) => res.json())
            .then((data) => {
                let jsonData = JSON.parse(JSON.stringify(data));
                //console.log(dataURI);
                this.setState(prevState => ({rows: [...prevState.rows, jsonData.result]}));
            })
            .catch((e) => console.log(`Error! ${e.message}`));
        }
    }

    viewMoreCall = () => {
      this.props.viewMore();
    }

    render() {
        //console.log(this.state.rows);
        return (
            <div>
                <ProgressBar now={45} />
                <Table striped bordered condensed hover responsive>
                  <thead>
                    <tr>
                      <th>#</th>
                      <th>Name</th>
                      <th>Full Address</th>
                      <th className="pno">Phone</th>
                      <th className="pno">International P.no</th>
                      <th>Website</th>
                      <th>Rating</th>
                    </tr>
                  </thead>
                  <tbody>
                    {this.state.rows.map(( listValue, index ) => {
                      return (
                        <tr key={index}>
                          <td>{listValue.index}</td>
                          <td>{listValue.name}</td>
                          <td>{listValue.formatted_address}</td>
                          <td>{listValue.formatted_phone_number}</td>
                          <td>{listValue.international_phone_number}</td>
                          <td><a href={listValue.website}>{listValue.website}</a></td>
                          <td>{listValue.rating}</td>
                        </tr>
                      );
                    })}
                  </tbody>
                </Table>
        <Button onClick={this.viewMoreCall} type="button">View More...</Button>
            </div>
        );
    }

}
export default Display;

2。 Display.js(子组件

time

当我点击查看在子组件中创建的更多按钮时,我改变了父组件的状态,但这样做不会返回更多记录。

我想要实现的是在用户点击查看更多按钮时将更多数据附加到现有表格。

1 个答案:

答案 0 :(得分:1)

componentDidMount仅在初始安装期间调用一次,因此您的this.state.rows之后不会更新。

添加componentDidUpdate以确保每当道具发生变化时都会获取新数据:

componentDidMount() {
  this.setData();
}

componentDidUpdate(prevProps) {
  if (this.props !== prevProps) { // only fetch if props changed
    this.setData();
  }
}

setData() {
  const { records, API, placeURI } = this.props;
  const results = records.results.map((p_id) => {
    const dataURI = `${placeURI}${p_id.place_id}${API}`;
    const proxyUrl = 'https://cors-anywhere.herokuapp.com/';
    return fetch(proxyUrl + dataURI)
      .then(res => res.json())
      .then((data) => {
        const jsonData = JSON.parse(JSON.stringify(data));
        // console.log(dataURI);
        return jsonData.result;
      });
  });
  // I wait for all fetch results before updating the state
  // If you prefer to update the state for each row, you can use your original code  
  Promise.all(results)
    .then(res =>
      this.setState(prevState => ({
        rows: [...prevState.rows, ...res],
      })))
    .catch(e => console.log(`Error! ${e.message}`));
}