在子组件之间共享父组件状态'州

Share parent state between child components' states?

本文关键字:组件 状态 之间 共享      更新时间:2023-09-26

学习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的"汽车"状态。因此,Calculator的状态未更新=> Dashboard的状态也未更新。

如何在滑块和仪表板之间共享计算器的父状态?

我知道,在SO上有很多类似的问题,但是很难找到具体的有用案例,特别是当你完全是React新手的时候。很抱歉重复了,

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

在你的例子中,cars应该是Calculator,Slide的状态,Dashboard应该只检索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>
    )
  }
})

应该尽可能少的组件具有状态,并且状态应该在树中尽可能高的位置。参见getInitialState中的Props是一个反模式

在React中,你希望有一个或多个"智能"组件,用于处理状态和"哑"组件。"智能"组件将状态传递给"愚蠢"组件。还注入事件处理程序,比如在您的例子中,用于更改汽车数量的处理程序。计算器是你的智能部件。它还应该有一个函数来处理状态变化。

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

也不要让你的初始状态从props(更多信息)。道具是可以改变的,直接在渲染函数中使用它们,像这样:

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);
},

将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>
    )
  }
})