仅渲染一次时更新组件(React)

时间:2018-04-19 06:17:39

标签: javascript reactjs google-maps

我需要帮助我如何使用标记列表填充Google地图标记,而不会在开始时渲染两次。在initMap方法中,循环将标记推送到组件状态中的markersList。我认为这是导致它在页面初始化时呈现两次的原因。我尝试过ComponentWillMount,但我不确定我是否正确使用它。

   class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      map: "",
      markersList: [],
      locations: [
        {
          title: "Powell's Books",
          address: "1005 W Burnside St, Portland, OR 97209",
          coordinates: {
            lat: 45.523096,
            lng: -122.681354
          }
        },
        {
          title: "Ground Kontrol",
          address: "511 NW Couch St, Portland, OR 97209",
          coordinates: {
            lat: 45.523943,
            lng: -122.675872
          }
        },
        {
          title: "Portland Art Museum",
          address: "1219 SW Park Ave, Portland, OR 97205",
          coordinates: {
            lat: 45.51615,
            lng: -122.683357
          }
        },
        {
          title: "Roseland Theater",
          address: "8 NW 6th Ave, Portland, OR 97209",
          coordinates: {
            lat: 45.52328,
            lng: -122.676297
          }
        },
        {
          title: "Voodoo Doughnuts",
          address: "22 SW 3rd Ave, Portland, OR 97204",
          coordinates: {
            lat: 45.522713,
            lng: -122.672944
          }
        },
        {
          title: "Arlene Schnitzer Concert Hall",
          address: "1037 SW Broadway, Portland, OR 97205",
          coordinates: {
            lat: 45.517197,
            lng: -122.681419
          }
        },
        {
          title: "Pioneer Place",
          address: "700 SW 5th Ave, Portland, OR 97204",
          coordinates: {
            lat: 45.518335,
            lng: -122.677261
          }
        }
      ]
    }
  }

  componentWillMount(){
    let infoWindow = new window.google.maps.InfoWindow();
    let locations = this.state.locations;
    let bounds = new window.google.maps.LatLngBounds();
    let tempArray = [];
    let listItem = document.getElementsByClassName("list-item")

    for (let i = 0; i < locations.length; i++) {

      let wikiUrl = "https://en.wikipedia.org/w/api.php?action=opensearch&origin=*&search=" + this.state.locations[i].title + "&format=json";

      let newMarker = new window.google.maps.Marker({
        map: newMap,
        position: locations[i].coordinates,
        title: locations[i].title,
        animation: window.google.maps.Animation.DROP,
        id: i
      });
      tempArray.push(newMarker);
      bounds.extend(newMarker.position);

      newMarker.addListener("click", function () {
        infoWindow.open(map, this);
        newMap.panTo(newMarker.position);
        axios.get(wikiUrl)
          .then(response => {
            const wikiInfo = response.data;
            infoWindow.setContent(`<p><strong>${wikiInfo[0]}</strong><br>${locations[i].address}</p><p>${wikiInfo[2][0]}</p><p>Click <a href='${wikiInfo[3][0]}' target='_blank'><strong>HERE</strong></a> for more information on ${wikiInfo[0]}.</p>`)
          })
      })

    }
    this.setState({
      markersList: tempArray
    })
    newMap.fitBounds(bounds);
  }

  componentDidMount() {
    this.initMap();
  }

  filterList = (event) => {
    let keyword = event.target.value;
    let filtered = this.state.markersList.filter(item => {

      return item.title.indexOf(keyword) > -1
    });
    this.setState({
      markersList: filtered
    })

  }
  initMap = () => {
    const map = document.querySelector(".map");

    let newMap = new window.google.maps.Map(map, {
      center: {
        lat: 45.519692,
        lng: -122.680496,
        mapTypeControl: false
      },
      zoom: 16
    });
    this.setState({
      map: newMap
    })
  }

  render() {
    return (

      <div>
        <div className="menu">
          <SearchInput
            change={this.filterList}
          />

          <ul className="location-list" >
            {

              this.state.markersList.map((marker, index) => {
                return <ListItem
                key={index}
                title={marker.title}
                />
              })
            }

          </ul>
        </div>
        <div className="map">

        </div>
      </div>

    );
  }
}

1 个答案:

答案 0 :(得分:0)

您可以使用shouldComponentUpdate来决定该组件是否应该重新渲染 https://codepen.io/cdeep/pen/MGJmMQ

您可以将地图保留在子组件中并通过道具发送位置,在这种情况下,您需要检查道具而不是状态。
nextProps.locations !== this.props.locations