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 id="app"></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学习笔记 】
版权声明:本博客属于个人维护博客,未经博主允许不得转载其中文章。