hguser
hguser

Reputation: 36068

State management in ReactJS

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

Answers (2)

smee
smee

Reputation: 231

To elaborate on the previous answer, the trick to mixing local state and global state is to:

  • Keep as much local as you can: the smaller the scope for any given item of state, the fewer bugs it will cause you.
  • Pass the state up to the parent when necessary (state lifting)
  • Be prepared for the parent to pass down new state that affects your stored local state.

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

RIYAJ KHAN
RIYAJ KHAN

Reputation: 15290

  1. 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.

  2. 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.

  3. 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

Related Questions