当父组件的状态更新时,React Child组件不会更新 [英] React Child component don't update when parent component's state update

查看:72
本文介绍了当父组件的状态更新时,React Child组件不会更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Google地方搜索API。当我从Google Place Search API获取一些数据时,它仅返回20条记录并给出下一个页面令牌以获取更多结果,然后我为每个位置获取 Place_id ,然后再次获取该位置的所有详细信息,因此我两次获取数据是创建两个组件,一个负责获取位置,这是我的父组件,另一个负责使用 place_id ,这是我的子组件。这是我的下面的代码

I'm working with Google place search API. When I fetch some Data from Google Place search API it only returns 20 records and gives a next page token for more results then I grab the Place_id for each place and then again I fetch all details of that place so I'm fetching data twice what I did is created two components, one is responsible for fetching places and it's my parent component and the other is responsible for fetching the place details using place_id and it's my child component. Here is my code below

1。 Extractor.js(父组件

1. Extractor.js (parent component)

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;

2。 Display.js(子组件

2. Display.js (Child component)

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;

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

when I click view more button created in the child component I change the state of parent component, But doing this is not returning more records.

我要实现的是,当用户单击查看更多按钮时,将更多数据追加到现有表中。

What I want to achieve is to append more data to my existing Table when user click view more button.

推荐答案

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

componentDidMount is only called once during initial mounting, so your this.state.rows does not get updated afterwards.

添加 componentDidUpdate 以确保每当道具更改时,都会获取新数据:

Add in componentDidUpdate to make sure new data is fetched whenever props have changed:

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

这篇关于当父组件的状态更新时,React Child组件不会更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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