在子组件的状态之间共享父状态?

Share parent state between child components' states?

学习 React,我正在构建一个简单的计算器。组件型号为:

- Calculator
  - Sliders (input[ref=cars])
  - Dashboard (p {this.state.cars})

Sliders 是具有一组输入的组件,应该通过父 Calculator 状态转移到 Dashboard

我的目标是使 Dashboard 中的状态值随 Sliders 的输入组件变化而变化。

var Calculator = React.createClass({
  getInitialState: function() {
    return {
      cars: 0
    };
  },
  render: function () {
    return (
      <div className="calculator">
        <Sliders
          cars={this.state.cars}
        />
        <Dashboard
          cars={this.state.cars}
        />
      </div>
    )
  }
});

var Dashboard = React.createClass({
  getInitialState:function () {
    return {
      cars: this.props.cars
    }
  },
  render: function () {
    return (
      <div>
        <h1>Dashboard</h1>
        <p>Cars: {this.state.cars}</p>
      </div>
    )
  }
})

var Sliders = React.createClass({
  getInitialState: function() {
    return {
      cars: this.props.cars
    };
  },
  handleInput: function () {
    var state = {
      cars: this.refs.cars.value
    }
    this.setState(state);
  },
  render: function () {
    return (
      <div className="sliders">
        <input type="text" ref="cars" onChange={this.handleInput} value={this.state.cars}/>
      </div>
    )
  }
})

据我所知,handleInput() 被触发,因此 Sliders 的状态已设置。但是,父 Calculator 的状态 'cars' 并不是 "transfered"。所以,Calculator 的状态没有更新 => Dashboard 状态也没有更新。

如何在 Sliders 和 Dashboard 之间共享计算器的父状态?

我知道,关于 SO 有很多类似的问题,但是很难找到具体有用的案例,尤其是当你完全是 React 的菜鸟时。所以,很抱歉重复了。

将 parent 作为 prop 传递给 slider,你就不需要 cars 作为 slider 中的状态。

这是一种方法,但 FelixKing 的回答更好。

var Calculator = React.createClass({
  getInitialState: function() {
    return {
      cars: 0
    };
  },
  handleInput: function () {
    var state = {
      cars: this.refs.cars.value
    }
    this.setState(state);
  },
  render: function () {
    return (
      <div className="calculator">
        <Sliders
          cars={this.state.cars} parent={this}
        />
        <Dashboard
          cars={this.state.cars}
        />
      </div>
    )
  }
});

var Dashboard = React.createClass({
  getInitialState:function () {
    return {
      cars: this.props.cars
    }
  },
  render: function () {
    return (
      <div>
        <h1>Dashboard</h1>
        <p>Cars: {this.state.cars}</p>
      </div>
    )
  }
})

var Sliders = React.createClass({
  getInitialState: function() {
    return {};
  },
  handleInput: function (value) {
    this.props.parent.handleInput(this.refs.cars.value);
  },

  render: function () {
    return (
      <div className="sliders">
        <input type="text" ref="cars" onChange={this.handleInput} value={this.props.cars}/>
      </div>
    )
  }
})

组件不共享状态。一个组件的状态可以成为另一个组件的道具。

在你的情况下,cars 应该是 Calculator, 的状态,SlideDashboard 应该只检索 cars 作为道具。如果输入更改,Sliders 应该通知 Calculator 更改,以便它可以更新其状态并重新渲染(这也会导致 SlidersCalculator 更新):

var Calculator = React.createClass({
  getInitialState: function() {
    return {
      cars: 0
    };
  },

  onUpdate: function (cars) {
    this.setState({cars});
  },

  render: function () {
    return (
      <div className="calculator">
        <Sliders
          cars={this.state.cars}
          onUpdate={this.onUpdate}
        />
        <Dashboard
          cars={this.state.cars}
        />
      </div>
    )
  }
});

var Dashboard = React.createClass({
  render: function () {
    return (
      <div>
        <h1>Dashboard</h1>
        <p>Cars: {this.props.cars}</p>
      </div>
    )
  }
})

var Sliders = React.createClass({
  handleInput: function (event) {
    this.props.onUpdate(event.target.value);
  },

  render: function () {
    return (
      <div className="sliders">
        <input type="text" ref="cars" onChange={this.handleInput} value={this.props.cars}/>
      </div>
    )
  }
})

尽可能少的组件应该有状态并且状态应该在树中尽可能高。另见 Props in getInitialState Is an Anti-Pattern

在 React 中,您希望拥有一个或多个 "smart" 组件,用于处理状态和 "dumb" 组件。 "smart" 组件将状态向下传输到 "dumb" 组件。还注入事件处理程序,例如在您的情况下是用于更改汽车数量的处理程序。 您的计算器是您的智能组件。它还应该具有处理状态更改的功能。

handleCarsChange: function( newAmount ) {
  this.setState({ cars: newAmount });
},

也不要从 props (more Information) 开始你的初始状态。道具是用来改变的,直接在你的渲染函数中使用它们,就像这样:

var Dashboard = React.createClass({
  render: function () {
    return (
      <div>
        <h1>Dashboard</h1>
        <p>Cars: {this.props.cars}</p>
      </div>
    )
  }
});

或者用 React 14 组件函数语法:

var Dashboard = function(props) {
    return (
      <div>
        <h1>Dashboard</h1>
        <p>Cars: {props.cars}</p>
      </div>
    );
};

最后但同样重要的是给 Sliders 组件一个处理函数来处理状态变化:

<Sliders
  cars={this.state.cars}
  handleCarsChange={this.handleCarsChange}
/>

并更改 Slider 组件中的 handleInput 函数:

handleInput: function(value) {
  this.props.handleCarsChange(this.refs.cars.value);
},