React学习笔记,五 状态提升

状态提升究竟是什么东西呢?别急,下面让我们一步一步来看看究竟要怎么使用状态提升

假设我们有这样一个需求,提供两个输入框(分别属于两个组件),保证输入框里面的内容同步

好,下面我们先来封装一个输入框组件 Input

class Input extends React.Component {
    constructor(props) {
        super(props)
        // 输入框里的内容保存在组件的 state 当中
        this.state = { content: '' }
        this.handleChange = this.handleChange.bind(this)
    }

    handleChange(e) {
        this.setState({ content: e.target.value })
    }

    render() {
        return (
            <input type='text' value={ this.state.content } onChange={ this.handleChange } />
        )
    }
}

然后我们另外定义一个组件 AllInput,在这个组件中包含两个 Input 组件,这样我们就得到两个输入框

class AllInput extends React.Component {
    constructor(props) {
        super(props)
    }
    
    render() {
        // 这里包含两个 `Input`  组件
        return (
            <div>
                <Input />
                <br /><br />
                <Input />
            </div>
        )
    }
}

好,下一个要解决的问题是怎么使两个输入框的内容同步

在两个 Input 组件中,它们各自的内容保存在各自的 state 当中,要怎么做才能使两个组件共享数据呢?

答案是 状态提升,即将两个组件需要共享的数据保存在共同的父组件中,然后子组件通过 props 获取父组件数据

也就是说,我们可以将两个子组件 Input 的数据保存在它们的父组件 AllInput 当中

我们先来看看怎么修改父组件的定义:

class AllInput extends React.Component {
    constructor(props) {
        super(props)
        // 在父组件中添加 state 对象,用于保存数据
        this.state = { content: '' }
        this.handleContentChange = this.handleContentChange.bind(this)
    }
    
    // 定义修改 state 的方法,通过 props 传递给子组件使用
    // 接收一个参数(新的数据)
    handleContentChange(newContent) {
        this.setState({ content: newContent })
    }
    
    render() {
        // 通过 props 将 state 和修改 state 的方法都传递给子组件
        return (
            <div>
                <Input content={ this.state.content } onContentChange={ this.handleContentChange }/>
                <br /><br />
                <Input content={ this.state.content } onContentChange={ this.handleContentChange }/>
            </div>
        )
    }
}

然后我们再来修改子组件定义:

class Input extends React.Component {
    constructor(props) {
        super(props)
        // 数据可以不再保存在子组件的 state 当中
        this.handleChange = this.handleChange.bind(this)
    }

    handleChange(e) {
        // 通过 props 获取父组件的 setState(修改数据的方法)
        // 传入一个参数(新的数据)
        this.props.onContentChange(e.target.value)
    }

    render() {
        // 通过 props 获取父组件的 state(数据)
        return (
            <input type='text' value={ this.props.content } onChange={ this.handleChange } />
        )
    }
}

通过状态提升,这样就可以实现组件之间的数据共享啦,一份完整的可运行的代码如下:

<!DOCTYPE html>
<html>

<head>
    <title>Demo</title>
    <script src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/babel-standalone"></script>
</head>

<body>
    <div ></div>

    <script type="text/babel">
        class Input extends React.Component {
            constructor(props) {
                super(props)
                this.handleChange = this.handleChange.bind(this)
            }

            handleChange(e) {
                this.props.onContentChange(e.target.value)
            }

            render() {
                return (
                    <input type='text' value={ this.props.content } onChange={ this.handleChange } />
                )
            }
        }
        
        class AllInput extends React.Component {
            constructor(props) {
                super(props)
                this.state = { content: '' }
                this.handleContentChange = this.handleContentChange.bind(this)
            }

            handleContentChange(newContent) {
                this.setState({ content: newContent })
            }

            render() {
                return (
                    <div>
                        <Input content={ this.state.content } onContentChange={ this.handleContentChange }/>
                        <br /><br />
                        <Input content={ this.state.content } onContentChange={ this.handleContentChange }/>
                    </div>
                )
            }
        }
        
        ReactDOM.render(
            <AllInput />,
            document.getElementById('app')
        )
    </script>
</body>

</html>

【 阅读更多 React 系列文章,请看 React学习笔记