简体   繁体   English

组件之间共享状态

[英]Sharing State Between Components

I want to make two components: App and Map. 我要制作两个组件:App和Map。 However when I try to make a new brand Map component and send the data from App to Map component, I cannot. 但是,当我尝试制作新的品牌Map组件并将数据从App发送到Map组件时,我无法。

My App (default) component holds the data as a state. 我的应用程序(默认)组件将数据保存为状态。 When I try to send this state to the Map component. 当我尝试将此状态发送到Map组件时。 It holds the data as a prop. 它以数据为支撑。

And of course If I don't separate them and write everything in App.js, everything works as I expected (markers shown on the map). 当然,如果我不分离它们并在App.js中编写所有内容,那么一切都会按我的预期工作(地图上显示的标记)。 But I want to control all states in the parent component. 但是我想控制父组件中的所有状态。

Am I violating a fundamental React rule? 我违反基本的React规则吗? How can I fix that? 我该如何解决?

App.js App.js

import React, { Component } from "react";
import "./App.css";
import Map from "./Map";

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      locations: [],
      markers: []
    };
  }

  componentDidMount() {
    fetch(
      "correct_foursquare_api_url"
    )
      .then(response => response.json())
      .then(data =>
        data.response.venues.map(place => ({
          id: place.id,
          name: place.name,
          lat: place.location.lat,
          lng: place.location.lng
        }))
      )
      .then(locations => {
        this.setState({ locations });
      });
  }

  render() {
    return (
      <div className="App">
      <Map locations={this.state.locations} />
      </div>
      )
  }
}

export default App;

Map.js Map.js

import React, { Component } from "react";
/* global google */

class Map extends Component {
  constructor(props) {
    super(props);
    this.state = {
      locations: [],
      markers: []
    };
  }

  componentDidMount() {
    this.callMap();
  }

  callMap() {
    window.initMap = this.initMap;
    loadJS(
      "api_url"
    );
  }

  // Map
  initMap = () => {
    const { locations, markers } = this.state;
    let map = new google.maps.Map(document.getElementById("map"), {
      center: { lat: 59.4827293, lng: -83.1405355 },
      zoom: 13
    });

    // Markers
    for (var i = 0; i < locations.length; i++) {
      var title = locations[i].name;
      var position = new google.maps.LatLng(locations[i].lat, locations[i].lng);
      var id = locations[i].id;
      var marker = new google.maps.Marker({
        map: map,
        position: position,
        title: title,
        animation: google.maps.Animation.DROP,
        id: id
      });
      markers.push(marker);
    }
  };

  render() {
    return <div id="map" />;
  }
}

function loadJS(src) {
  var ref = window.document.getElementsByTagName("script")[0];
  var script = window.document.createElement("script");
  script.src = src;
  script.async = true;
  ref.parentNode.insertBefore(script, ref);
}

export default Map;

You store your locations in the state of the App component, but you also have locations in state of the Map component that you use on mount. 您将locations存储在App组件的状态下,但是在安装时也使用了处于Map组件状态的locations

You could instead wait with rendering the Map component until the locations request is finished, and then use the locations props in the Map component passed down from App instead. 相反,您可以等待渲染Map组件,直到完成locations请求,然后使用从App传递来的Map组件中的locations道具。

Example

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      locations: [],
      markers: []
    };
  }

  componentDidMount() {
    fetch("correct_foursquare_api_url")
      .then(response => response.json())
      .then(data => {
        const locations = data.response.venues.map(place => ({
          id: place.id,
          name: place.name,
          lat: place.location.lat,
          lng: place.location.lng
        }));

        this.setState({ locations });
      });
  }

  render() {
    const { locations, markers } = this.state;

    if (locations.length === 0) {
      return null;
    }

    return (
      <div className="App">
        <Map locations={locations} markers={markers} />
      </div>
    );
  }
}

class Map extends Component {
  // ...

  initMap = () => {
    const { locations, markers } = this.props;

    // ...
  };

  // ...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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