简体   繁体   中英

State of React child doesn't update after updating parent component

I try to update the center prop of the child BaseMap component via the parent component. Even though the parent components state gets updated (and I could read the new updated properties in the console.log ), it is not passed down to the child properties.

The last thing I tried was the componentWillReceiveProps method. It still doesn't work.

This is my code:

const google = window.google;
let geocoder = new google.maps.Geocoder();

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      avatar: '',
      username: 'someUse03',
      realName: '',
      location: '',
      followers: '',
      following: '',
      repos: '',
      address: '',
      }
  }

  render() {
    return (
      <div>
        <SearchBox fetchUser={this.fetchUser.bind(this)}/>
        <Card data={this.state} />
        <BaseMap />
      </div>
    );
  }

  fetchApi(url) {
    fetch(url)
      .then((res) => res.json())
      .then((data) => {
        this.setState({
          avatar: data.avatar_url,
          username: data.login,
          realName: data.name,
          location: data.location,
          followers: data.followers,
          following: data.following,
          repos: data.public_repos,
          address: geocoder.geocode({'address': data.location}, function(results, status) {
            if (status == 'OK') {
              var coords = [];
              var results = results.map((i) => {
                i.geometry.location = i.geometry.location
                          .toString()
                          .replace(/[()]/g, '')
                          .split(', ');
                coords.push(i.geometry.location[0], i.geometry.location[1]);
                results = coords.map((i) => {
                  return parseInt(i, 10)
                });
                return results;
              });
            } else {
              alert('Geocoding was not successfull because ' + status)
            }
          })
        })
      });
  }

  fetchUser(username) {
    let url = `https://api.github.com/users/${username}`;

    this.fetchApi(url);
  }

  componentDidMount() {
    let url = `https://api.github.com/users/${this.state.username}`;

    this.fetchApi(url);
  }

}

export default App;

This is the child component:

BaseMap extends React.Component {
        constructor(props) {
            super(props);
            this.state = {
                center: [41, 21],
            }
        }

        componentWillReceiveProps(nextProps) {
            this.setState({ center: nextProps.address});
        }

        render() {
            return (
                <Col md={10} mdPull={1}>
                    <div className="map">
                        <GoogleMap
                        bootstrapURLKeys={'AIzaSyBhzwgQ3EfoIRYT70fbjrWASQVwO63MKu4'}
                        center={this.state.center}
                        zoom={11}>
                        </GoogleMap>
                    </div>
                </Col>
            );
        }
    }

You are fetching inside the render method. this is a big NO NO .
Instead do that in the componentDidMount life cycle method

Another thing that may or may not be related to your problem, Arrays are reference types, that means if you mutate them they still points to the same ref in the memory. this could be problematic for the Reconciliation and diff algorithm of react to determine if the state indeed changed.
when you want to change or return a new array you could simply use the ES6 spread operator :

const nextArray = [...nextProps.address]
this.setState({ center: nextArray });

EDIT
Ok i forgot to mention the most important part here :)
You are not passing any props to <BaseMap /> so you won't get any helpful data in componentWillReceiveProps .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM