我正在研究React文档的这一部分:https://reactjs.org/docs/lifting-state-up.html.
在我的一个项目中,我也遇到了类似的问题,但略有不同。我们可以使用与文档相同的示例,并进行一些修改以适应我的问题:假设我有<Sensor />
组件而不是<TemperatureInput />
。该传感器以两种不同形式的输入捕获温度和压力。我的第一个想法是捕获这些压力和温度输入,然后打开State,然后将其传递给Sensor的props changeHandler函数,该函数实际上是一个定义并在父组件上工作的函数。最后一部分是React文档所建议的,尽管它们没有将State传递给函数,而是简单地传递一个变量(event.target.value(
class Sensor extends React.Component {
constructor(props) {
super(props);
this.state = {temperature:'',
pressure: ''}
this.handleTemperatureChange = this.handleTemperatureChange.bind(this);
this.handlePressureChange = this.handlePressureChange.bind(this);
}
handleTemperatureChange(e) {
this.setState(temperature:e.target.value);
this.props.onChange(this.state);
}
handlePressureChange(e) {
this.setState(pressure:e.target.value);
this.props.onChange(this.state);
}
render() {
const temperature = this.props.temperature;
return (
<fieldset>
<legend>Enter temperature and pressure:</legend>
<input value={this.state.temperature}
onChange={this.handleTemperatureChange} />
<input value={this.state.pressure}
onChange={this.handlePressureChange} />
</fieldset>
);
}
}
我修改后的方法唯一的问题是State异步更新,所以当我将State传递给onChange props函数时,我实际上可能正在传递以前的状态。
我不知道该怎么处理。
正确。React状态更新是异步的,因此,如果在将更新排队后立即尝试访问状态,它仍然是当前渲染周期中的状态,而不是您期望在下一个呈现周期中看到的状态。
使用组件生命周期方法(如componentDidUpdate
(来处理对状态更新的"反应",并正确地发出副作用,如调用传递的回调
class Sensor extends React.Component {
...
handleTemperatureChange(e) {
this.setState(temperature:e.target.value);
}
handlePressureChange(e) {
this.setState(pressure:e.target.value);
}
componentDidUpdate(prevProps, prevState) {
const { pressure, temperature } = this.state;
if (prevState.pressure !=== pressure ||
prevState.temperature !== temperature
) {
this.props.onChange(state);
}
}
render() {
...
}
}
一个替代方案是在状态更新后使用this.setState
回调函数(第二个参数(运行函数,尽管我认为应该避免这种模式。(IMO如果滥用,可能会导致比解决更多的问题,只需坚持使用生命周期功能即可(
class Sensor extends React.Component {
...
handleTemperatureChange(e) {
this.setState(
temperature:e.target.value,
() => this.props.onChange(this.state),
);
}
handlePressureChange(e) {
this.setState(
pressure:e.target.value,
() => this.props.onChange(this.state),
);
}
render() {
...
}
看起来好像你的树中有一些的压力和温度状态,所以我很好奇是否是这样,简单地将它们作为道具代理到输入是否更有意义,比如:
const Sensor = ({ pressure, onChange, temperature }) => {
const handleTemperatureChange = (e) => {
onChange({ temperature: e.target.value });
}
const handlePressureChange = (e) => {
onChange({ pressure: e.target.value });
}
return (
<fieldset>
<legend>Enter temperature and pressure:</legend>
<input value={temperature} onChange={handleTemperatureChange} />
<input value={pressure} onChange={handlePressureChange} />
</fieldset>
);
}
setState
接收一个回调,该回调将在应用状态更改后激发。您可以在这里的文档中看到这一点。
this.setState({ ... }, () => this.props.onChange(this.state));