react 状态提升

状态提升是什么意思? 一个最简单的例子,就是如果两个子组件需要利用到对方的状态的话,那么这个时候我们就需要使用到状态提升,具体的做法就是把两个子组件的状态写到它们的父组件当中,然后父组件把状态传递到子组件的props中去,这样子组件也相当于有状态。父组件相当于是数据源,这样的话,子组件是没有控制权的,那么如果之前子组件的state是受到控制的怎么办呢?就像我们之前说到的受控组件一样,像:

<input value = {this.state.value} onChange = {this.handleChange}/>

那我们就得在父组件中写出子组件的处理函数,并在处理函数中更改父组件的state

来看一个完整的状态提升的例子:

先写一个温度输入组件:

class TemperatureInput extends React.Component {
    state = {
        temperature: ''
    };
    handleChange = (e) => {
        this.setState({
            temperature : e.target.value
        })
    };
    render() {
        return (
            <fieldset>
                <legend>输入{scaleNames[this.props.scale]}:</legend>
                <input type="number" value={this.state.temperature} onChange={this.handleChange}
            </fieldset>
        )
    }
}

这个组件就是一个普通的受控组件,有stateprops以及处理函数。

我们在写另一个组件:

class Calculator extends React.Component {
    render () {
        return (
            <div>
                <TemperatureInput scale='c'/>
                <TemperatureInput scale='f'/>
            </div>
        )
    }
}

这个组件现在没有什么存在的价值,我们仅仅是给两个温度输入组件提供一个父组件,以便我们进行后续的状态提升

现在我们看看网页的样子:


我们可以输入摄氏度和华氏度,但是我们现在想要让这两个温度保持一致,就是我们如果输入摄氏度,那么下面的华氏度可以自动算出来,如果我们输入华氏度,那么摄氏度就可以自动算出来。

那么我们按照现在这种结构的话,是非常难以实现的,因为我们知道这两个组件之间没有任何关系,它们之间是不知道对方的存在,所以我们需要把它们的状态进行提升,提升到它们的父组件当中。

那我们看看如何做修改,首先把子组件(温度输入组件)的状态(state)全部删除,看看是什么样子:

    class TemperatureInput extends React.Component {

        handleChange = (e) => {

        };

        render() {
            return (
                <fieldset>
                    <legend>输入{scaleNames[this.props.scale]}:</legend>
                    <input type="number" value={this.props.temperature} onChange={this.handleChange}/>
                </fieldset>
            )
        }
    }

可以看到所有与state有关的东西全部删掉了,然后inputvalue也变成了props,通过父组件传入。那么现在这个温度输入组件其实就是一个受控组件了,仔细回忆一下我们之前讲的受控组件,看看是不是这样意思?

我们通常会在受控组件发生改变的时候传入一个onChange函数来改变受控组件的状态,那么我们这里也是一样,我们通过给 温度输入组件 传入某个函数来让 温度输入组件 中的input发生变化的时候调用,当然这个函数我们可以随意命名,假如我们这里叫做onTemperatureChange函数,那么我们继续修改子组件:

    class TemperatureInput extends React.Component {

        handleChange = (e) => {
            this.props.onTemperatureChange(e.target.value);
        };

        render() {
            return (
                <fieldset>
                    <legend>输入{scaleNames[this.props.scale]}:</legend>
                    <input type="number" value={this.props.temperature} onChange={this.handleChange}/>
                </fieldset>
            )
        }
    }

好了,我们的子组件差不多就是这样了,当然我们可以省略那个handleChange函数,因为可以看到这个函数就是调用了一下那个props里的函数,所以我们完全把inputonChange这么写
<input type="number" value={this.props.temperature} onChange={this.props.onTemperatureChange}/>这么写的话注意onTemperatrueChange函数的参数是那个事件,而不是我这里写的e.target.value

再看看我们的父组件如何修改,我们首先补上state,以及子组件对应的onChange处理方法,以及子组件的值。写好之后大概是这个样子:

    class Calculator extends React.Component {
        state = {
            celsius: '',
            fahrenheit: ''
        };

        onCelsiusChange = (value) => {
            this.setState({
                celsius: value,
                fahrenheit: tryConvert(value, toFahrenheit)
            });
        };

        onFahrenheitChange = (value) => {
            this.setState({
                celsius: tryConvert(value, toCelsius),
                fahrenheit: value
            });
        };

        render() {
            return (
                <div>
                    <TemperatureInput scale='c' temperature={this.state.celsius}
                                      onTemperatureChange={this.onCelsiusChange}/>
                    <TemperatureInput scale='f' temperature={this.state.fahrenheit}
                                      onTemperatureChange={this.onFahrenheitChange}/>
                </div>
            )
        }
    }

这里我们省略的摄氏度与华氏度的转换函数,比较简单,大家自行搜索方法。

最后加上我们的 水是否能够烧开的组件。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 状态提升 通常情况下,同一个数据的变化需要几个不同的组件来反映。我们建议提升共享的状态到它们最近的祖先组件中。我们...
    初漾流影阅读 697评论 0 0
  • 最近看了一本关于学习方法论的书,强调了记笔记和坚持的重要性。这几天也刚好在学习React,所以我打算每天坚持一篇R...
    gaoer1938阅读 1,721评论 0 5
  • 说在前面 关于 react 的总结过去半年就一直碎碎念着要搞起来,各(wo)种(tai)原(lan)因(le)。心...
    陈嘻嘻啊阅读 6,917评论 7 41
  • 通常,几个组件需要根据同一个数据变化做出响应。我们建议将这个共享的状态提升到他们最近的一个共用祖先。让我们看看实际...
    莫铭阅读 911评论 0 1
  • 本笔记基于React官方文档,当前React版本号为15.4.0。 1. 安装 1.1 尝试 开始之前可以先去co...
    Awey阅读 7,805评论 14 128