Why is my react component not updating with state updates?

I have a map app I built that requires some map icons to appear/disappear after a button press, but I can’t figure out how to set it to re-render the component when I pass in a new sports property from it’s parents component :

Parent loads component:

<SimpleMap sports=[default value and future values go here] />

Simple map component(simplified):
constructor(props) {
  (props);
  this.state = {
    events: [{venue: {lat: 2, lon: 1}}],
    sports: ["baseball", "football",  "paddle", "soccer", "boxing", "dart", "biking", "golf", "hockey", "inline-skating", "tennis", "volleyball", "skateboard", "kickball", "bowling", "pool", "ride", "hike", "ice-skating"]
  };
};

componentWillReceiveProps (nextProps) {
  this.setState({events: [{venue: {lat: 2, lon: 1}}],
                  sports: nextProps.sports});
  console.log(nextProps.sports);
}

static defaultProps = {
  center: {lat: 36.160338, lng: -86.778780},
  zoom: 12,
  sports: ["baseball", "football",  "paddle", "soccer", "boxing", "dart", "biking", "golf", "hockey", "inline-skating", "tennis", "volleyball", "skateboard", "kickball", "bowling", "pool", "ride", "hike", "ice-skating"],
};

makeMapEvents (insertProps) {
  fetch("./json/meetup.json").then((response) => {
    return response.json()
  }).then((response) => {
    /* eventually returns new events object based on insertProps */
    this.setState({events: response});
  }
};

componentDidMount () {
  this.makeMapEvents(this.state.sports);
  console.log("mounted", this.state.sports);
}

Eventually ends up here to map events from state:
<GoogleMap>
  {this.state.events.map((result) => {
     return (<Marker key={counter++} lat={result.venue.lat} lng={result.venue.lon} 
                sport={this.props.sport} data={result}/>);
  })}
</GoogleMap>

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

React ES6 classes do not autobind this by default to non-react base member methods. Therefore, the context for this in your function makeMapEvents is not bound correctly. There are 2 ways to fix this:

Via ES7 property initializer:

makeMapEvents = (insertProps) => {
  fetch("./json/meetup.json").then((response) => {
    return response.json()
  }).then((response) => {
    /* eventually returns new events object based on insertProps */
    this.setState({events: response});
  })
};

Via binding in constructor:
constructor(props) {
  (props);
  this.state = {
    events: [{venue: {lat: 2, lon: 1}}],
    sports: ["baseball", "football",  "paddle", "soccer", "boxing", "dart", "biking", "golf", "hockey", "inline-skating", "tennis", "volleyball", "skateboard", "kickball", "bowling", "pool", "ride", "hike", "ice-skating"]
  };

  this.makeMapEvents = this.makeMapEvents.bind(this) // << important line


}

Method 2

.then((response) => {
    this.setState({events: resp});
}

You take in parameter response then try to use resp which isnt the variable you want.

Method 3

The probable cause is that your makeMapEvents() function doesn’t provide the correct lexical value of this when calling this.setState() and as a result your code doesn’t work. Change the makeMapEvents() function definition to use Arrow function (() => {}) and provide correct lexically bound value of this as:

makeMapEvents = (insertProps) => {
  fetch("./json/meetup.json").then((response) => {
    return response.json()
  }).then((response) => {
    this.setState({events: response});
  }); // <-- Typo here. The closing parenthesis is missing
};

Also there is a typo in your code wherein the closing parenthesis is missing as shown in comments above

Method 4

You are mixing up props and state in the component. sports should only be in props, it shouldn’t be in state as it is being passed in from the parent component.

constructor(props) {
  (props);
  this.state = {
    events: [{venue: {lat: 2, lon: 1}}] <== removed sports here, it didn't belong
};

componentWillReceiveProps (nextProps) {
  this.setState({events: [{venue: {lat: 2, lon: 1}}],
                  sports: nextProps.sports});
  console.log(nextProps.sports);
}

static defaultProps = {
  center: {lat: 36.160338, lng: -86.778780},
  zoom: 12,
  sports: ["baseball", "football",  "paddle", "soccer", "boxing", "dart", "biking", "golf", "hockey", "inline-skating", "tennis", "volleyball", "skateboard", "kickball", "bowling", "pool", "ride", "hike", "ice-skating"],
};

makeMapEvents (insertProps) {
  fetch("./json/meetup.json").then((response) => {
    return response.json()
  }).then((response) => {
    /* eventually returns new events object based on insertProps */
    this.setState({events: response});
  }
};

componentDidMount () {
  this.makeMapEvents(this.props.sports);  <== changed to props.sports
  console.log("mounted", this.props.sports); <== changed to props.sports
}


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x