ReactJS 中的状态管理

State management in ReactJS

我正在构建一个地图相关组件,其中 center zoom features 等属性将由 props 推送到该组件。当地图组件挂载后,我会根据props设置地图视图并添加一些功能。

当状态改变时,我不确定 componentWillReceiveProps 更新地图视图是否正确。

此外,当用户与地图交互时,地图视图会发生变化,这意味着地图组件的内部状态发生了变化,是否需要通过setState更新状态以保持状态一致性?

  1. 对于initial rendering and initialisation,可以将props从父组件传给Map组件。

    例如初始缩放、地理围栏、默认标记等

  2. 现在从这里开始,如果地图组件有任何变化,比如新标记,地理围栏,那么你应该manage local state at Map Component level and store the state internally with state。如果 APP 需要有关此更改数据的一些信息,请执行 state lifting.

  3. 在APP中,如果Map组件再次发生变化,比如重置Map Component,你应该使用componentWillReceiveProps获取props,然后setState渲染Map使用这些新重置 data.Now 再次组件,这些新传递的道具将保存在组件状态中。

为了详细说明之前的答案,混合局部状态和全局状态的技巧是:

  • 尽可能保持本地化:任何给定状态项的范围越小,它给您带来的错误就越少。
  • 必要时将状态传递到 parent(状态提升)
  • 为 parent 传递影响您存储的本地状态的新状态做好准备。

这是一个演示如何完成的示例。我刚刚从 create-react-app 中获取了一个入门应用程序,并添加了一个带有缩放 属性 的 "Map" 组件作为示例。

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;

所以你可以在这里看到缩放状态一直停留在地图组件中,直到用户按下保存按钮。那时,它被提升到 parent(App 组件),它将它保存在自己的状态中。然后调用 componentWillReceiveProps() 为 re-rendering 准备 Map 组件,并且 Map 组件再次更新其状态(在本例中为相同的值,但在其他情况下可能不同)。