Why is my response component not updating with state update?

I have a map application that I built for which some map icons appear / disappear after clicking a button, but I can’t figure out how to configure it to re-render the component when I pass a new sports property from this parent component:

Parental component:

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

Simple card 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); } 

In the end, it ends here to display events from a 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> 
+7
javascript reactjs
source share
4 answers

React ES6 classes are not autobind this by default do not respond to methods of the base element. Therefore, the context for this in your makeMapEvents function makeMapEvents not bound correctly. There are two ways to fix this:

Via the 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}); }) }; 

Through binding in the 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 } 
+3
source share
 .then((response) => { this.setState({events: resp}); } 

Take the response parameter, then try using resp , which is not the variable you want.

+2
source share

The likely reason is that your makeMapEvents() function does not provide the correct lexical value for this when calling this.setState() , and as a result, your code does not work. Change the definition of the makeMapEvents() function to use the Arrow Function ( () => {} ) and specify the correct lexically related value for 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 }; 

There is also a typo in your code in which there is no closing bracket, as shown in the comments above

+1
source share

You mix the details and state in the component. the sport should only be in the details, it should not be in a state, since it is transmitted 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 } 
+1
source share

All Articles