我正在React工程中使用Google Maps API进行地图的简单实现。当用户单击基于状态对象中infoWindowStatus的状态的标记时,向他们显示一个信息窗口。如果infoWindowStatus为true,则显示信息窗口。

如果我直接更改状态并使用forceUpdate,则信息窗口会正确显示。当我使用setState时,不会显示信息窗口。 (但是,当我console.log this.state.locations [myKey] .infoWindowStatus时,我可以看到infoWindowStatus确实从false变为true。)

我遇到的问题是:
使用this.setState和来自immutability-helper的更新不会重新渲染React组件。

import update from 'immutability-helper';

state = {

  locations : [
      {
      position: {lat: 41.3029876, lng: -72.9191306},
      title: "Pepe's Pizza",
      mappy: '',
      infoWindowStatus: false,
      key : 0,
      infoWindow :
          {
            content : "Loading...",
            contentUrl : ""
          }
      }
    ]
}

// THIS DODGEY CODE WORKS
this.state.locations[myKey].infoWindowStatus = true;
this.forceUpdate()

//THIS CODE DOES NOT WORK
this.setState(
 { locations: update(this.state.locations, { [myKey] : {infoWindowStatus:
 {$set:true}}})
      }
);


要求的整个组件是:

import React, { Component } from 'react';
import './css/App.css';
import './css/Custom.css';
import NeighborhoodMap from './neighborhoodMap';
import 'typeface-roboto';
import escapeRegEx from 'escape-string-regexp';
import update from 'immutability-helper';

class App extends Component {

    state = {

  locations : [
      {
      position: {lat: 41.3029876, lng: -72.9191306},
      title: "Pepe's Pizza",
      mappy: '',
      infoWindowStatus: false,
      key : 0,
      infoWindow :
          {
            content : "Loading...",
            contentUrl : ""
          }
      }
    ]
}


// TODO: separate data into external data file.

componentDidMount(){


this.setState({
    filteredLocationsOnly : this.state.locations
  })
}

// Launches Info Window on Google Map
showInfoWindowNow(locationSelected){
    let myKey;

    this.state.locations.filter( (location) =>{
       if (locationSelected.name === location.title || locationSelected.title === location.title){
         myKey = location.key;
         return location
       }
    } );
    this.updateInfoWindowContentAgain(myKey);


// // THIS CODE DOES NOT WORK AT ALL
// this.setState({ locations[myKey].infoWindowStatus : true })


// // THIS CODE DOESN'T SHOW THE INFO WINDOW
// console.log("Status: ", this.state.locations[myKey].infoWindowStatus);
// const tempLocations = [...this.state.locations];
// tempLocations[myKey] = { ...tempLocations[myKey], infoWindowStatus: true };
//
//  this.setState(
//        {
//          locations: tempLocations
//        }
//  );
// console.log("Status Now: ", this.state.locations[myKey].infoWindowStatus);


// THIS DODGEY CODE WORKS
// https://stackoverflow.com/questions/51250518

this.state.locations[myKey].infoWindowStatus = true;
this.forceUpdate()


} //showInfoWindowNow


// Close Info Window on Google Map
closeInfoWindowNow(locationSelected){
  this.forceUpdate()
}

// Update Content for Info Window
updateInfoWindowContentAgain(myKey){
  return this.getInfoWindowContent(this.state.locations[myKey].title, myKey);
}

// Update Content for Info Window sub-function
getInfoWindowContent(searchTerm, myKey){
var nytAuthKey = "3d6801dab968446787ea71d5042ad8f7";
var myNewYorkTimesUrl = `https://api.nytimes.com/svc/search/v2/articlesearch.json?&api-key=${nytAuthKey}&q=${searchTerm}`

var contentForLocation;
var contentUrl;

let content = fetch(myNewYorkTimesUrl)
  .then(response => response.json() )
    .then(data => {
        return addArticles(data);
  }
 )
 .catch(error => requestError(error, 'articles'));

// add text from fetch request
function addArticles(data){
  if (data.response && data.response.docs && data.response.docs.length > 1){
    const articles = data.response.docs;
    // var content, contentUrl;
    let infoWindow  = {};

      articles.map(article => {
          infoWindow.content = `${article.snippet}`;
          infoWindow.contentUrl = `${article.web_url}`;
          contentForLocation = `${article.snippet}`;
          contentUrl = `${article.web_url}`;
          return infoWindow;
    });
  }
}  //addArticles


// Handle Errors
function requestError(error, part) {
   console.log("Error: ", error);
}


content.then( content => {
  this.state.locations[myKey].infoWindow.content = (contentForLocation);
  this.state.locations[myKey].infoWindow.contentUrl = contentUrl;
  this.forceUpdate()
}


)} // getInfoWindowContent
// end Nyt


filterLocations(query){
  const match = new RegExp(escapeRegEx(query), 'i')
  let showingLocations = this.state.locations.filter((location) => {
    return match.test(location.title);
  });

  this.setState({
    filteredLocationsOnly : showingLocations
  })
}  // end filterLocations

clearQuery = () => {
        this.setState({query : ''});

}

updateQuery = (query) => {
          this.setState({query : query.trim()})
          this.filterLocations(query);
}


render() {
 return (
  <div className="App">
        <NeighborhoodMap
        menuOpen = {this.state.menuOpen}
        locations = {this.state.locations}
        filteredLocationsOnly = {this.state.filteredLocationsOnly}
        query = {this.state.query}
        updateQuery = { (query) => {
          this.updateQuery(query)
        }}
        clearQuery = { () => {
          this.clearQuery()
        }}
        filterLocations = { (query) => {
          this.filterLocations(query)
        }}

        infoWindowStatus = {this.state.infoWindowStatus}
        showInfoWindowNow = { (location) => {
          this.showInfoWindowNow(location)
        }}
        closeInfoWindowNow = { (location) => {
          this.closeInfoWindowNow(location)
        }}
        updateInfoWindowContentAgain = { (id) => {
          this.updateInfoWindowContentAgain(id)
        }}
        infoWindow = {this.state.infoWindow}
        />
   </div>

    ) // return
  }// render
} // Component

export default App;

最佳答案

您可以跳过不变性助手,而复制locations数组,创建locations[myKey]副本,然后覆盖infoWindowStatus

const locations = [...this.state.locations];
locations[myKey] = { ...locations[myKey], infoWindowStatus: true };
this.setState({ locations });


另外,您赋予infoWindowStatusNeighborhoodMap来自this.state.infoWindowStatus,但是将其存储在this.state.locations[0].infoWindowStatus中。

关于javascript - 使用this.setState和来自immutability-helper的更新不会重新渲染React组件,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51250518/

10-10 14:13