狀態提升究竟是什么東西呢?別急,下面讓我們一步一步來看看究竟要怎么使用狀態提升
假設我們有這樣一個需求,提供兩個輸入框(分別屬於兩個組件),保證輸入框里面的內容同步
好,下面我們先來封裝一個輸入框組件 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學習筆記 】