Reputation: 36068
I am building a map related component where the properties like center
zoom
features
will be pushed to the component by props
. When the map component are mounted, I will set the map view and add some features according to the props
.
And when the state changed I am not sure if updating the map view by componentWillReceiveProps
is the right way.
Also, when user intereact with the map, the map view will change which means the internal state of the map compontent have changed, is it necessary to update the state by setState
to keep the state consistency?
Upvotes: 0
Views: 384
Reputation: 231
To elaborate on the previous answer, the trick to mixing local state and global state is to:
Here's an example that demonstrates how this is done. I've just taken a starter app from create-react-app
and added a "Map" component with a zoom property as an example.
App.js
import React, { Component } from 'react';
import logo from './logo.svg';
import Map from './Map';
import './App.css';
class App extends Component {
constructor(props) {
super(props);
this.state = {zoom: 1.0}
this.handleZoomChange = this.handleZoomChange.bind(this);
}
handleZoomChange(zoom) {
this.setState( {zoom: zoom} );
}
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Welcome to React</h1>
</header>
<p className="App-intro">
<Map zoom={this.state.zoom} onZoomChange={this.handleZoomChange}/>
</p>
</div>
);
}
}
export default App;
Map.js
import React, { Component } from 'react';
class Map extends Component {
constructor(props) {
super(props);
this.state = {zoom: this.props.zoom}
this.handleSubmit = this.handleSubmit.bind(this);
this.handleChange = this.handleChange.bind(this);
}
// Called when the parent wants us to re-render with
// new props. Note that the new props may be the same
// as the old ones.
componentWillReceiveProps(nextProps) {
if( nextProps.zoom ) {
this.setState( {zoom: nextProps.zoom } );
}
}
// User submits the form. Pass it up to our parent.
handleSubmit(e) {
e.preventDefault();
this.props.onZoomChange(this.state.zoom);
}
// Control the input field
handleChange(e) {
this.setState( {zoom: e.target.value} );
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<input type="text" value={this.state.zoom} onChange={this.handleChange}/>
<button type="submit">Save</button>
</form>
);
}
};
export default Map;
So you can see here that the zoom state stays within the Map component until the user presses the Save button. At that point, it gets lifted to the parent (the App component), which saves it in its own state. Then componentWillReceiveProps() is called to prepare the Map component for re-rendering and the Map component updates its state again (in this case to the same value, but it might not be in other circumstances).
Upvotes: 3
Reputation: 15290
For initial rendering and initialisation
, one can passed down the props
from parent component to Map Component.
e.g. Initial zoom, geofence, default marker etc.
Now from here onwards, if Map component have any changes, like new mark, geofence then you should manage local state at Map Component level and store the state internally with state
. In case,APP need some info on this changed data then do state lifting
.
From APP,if again there is changes for Map component like resetting the Map Component, you should use componentWillReceiveProps
to retrieve the props and do setState
to render the Map Component again with these new reset data.Now,these new passed props going to save in Component state.
Upvotes: 1