React 是 Facebook 創造的 JavaScript 庫。雖然在 React 中處理數據顯得有點復雜,但其實並沒有那么棘手。最近我總結了三種在 React 中進行數據處理的方法:
- 使用 Props 從父組件傳遞數據到子組件
- 使用回調函數從子組件傳遞數據到父組件
- 非父子組件之間傳遞數據:
- 結合 Props 和回調函數
- 使用 Redux 傳遞數據
- 使用 React Context API 傳遞數據
這篇文章中主要總結了這些實現方式,新手可以從中縱覽全局。
使用 Props 從父組件傳遞數據到子組件
假設我們的目錄結構如下所示:
App
└── Parent
├── Child1
└── Child2
這是 React 中最簡單也是最基礎的數據流向。
class Parent extends React.Component {
state = { data : "Hello World" }
render() {
return (
<div>
<Child1/> // 無數據傳遞
<Child2 dataFromParent = {this.state.data} />
</div>
);
}
}
// 沒有強制要求必須傳遞 state 中的值,通過 var 或者 const 定義的變量也可以從父組件傳遞給子組件
在子組件中,可以非常簡單地使用 this.props.dataFromParent
(只是一個通過 props 傳遞的變量) 來獲取到從父組件傳遞過來的數據。
class Child2 extends React.Component {
render() {
return (
<div>
The data from parent is:{this.props.dataFromParent}
</div>
);
}
}
使用回調函數從子組件傳遞數據給父組件
如果我要從 Child1 子組件中傳遞信息——“美女,最近還好嗎?” 給父組件,應該怎么做呢?為了實現這個目的,需要按照以下步驟進行操作:
第一步:在父組件中定義一個有參數的回調函數
第二步:將該回調函數作為 Props 傳遞到 Child1 子組件
class Parent extends React.Component {
state = { message: "" }
callbackFunction = (childData) => {
this.setState({message: childData})
},
render() {
return (
<div>
<Child1 parentCallback = {this.callbackFunction}/>
<p> {this.state.message} </p>
</div>
);
}
}
第三步:在子組件中,通過調用 this.props.callback(dataToParent)
將數據 dataToParent
傳遞給父組件
class Child1 extends React.Component{
sendData = () => {
this.props.parentCallback("美女,最近還好嗎?");
},
render() {
//在想傳遞信息給父組件的任意時刻調用 sendData 方法
}
};
非父子組件之間傳遞數據
當我還是一個初學者的時候,選擇哪種方式進行非父子組件間通訊對我來說是一個難題。現在我知道有以下三種方式,並且每種方式都有自己的優缺點。
方式1:結合 Props 和回調函數
這種方式不適用復雜的組件樹,因為這將有一大部分進行數據傳遞的代碼要寫,而且需要中間層進行數據的傳遞,雖然可能它們並不需要該數據。
方式2:使用 Redux 傳遞數據
方式3:使用 React Context API 傳遞數據
現在有很多關於為什么 React 增強了 Context API 以及在何場景下哪種方式更優的文章。以下是兩篇推薦:
React Context API — A Replacement for Redux?
我使用過這種方式,相比 Redux,我更傾向於使用該方式。
Context API 的最大優勢是:這種方式使開發者從 “Prop 深淵”中解放出來。(Props 深淵是指傳遞數據到子組件中。主要的思路是函數式編程,不斷地將參數傳遞給下一個函數)
建設我們有以下的組件樹,想要從 Child1 中傳遞信息“SSup brother?”給組件 Child2。
App
├── Child1
└── Child2
第一步:為兩個子組件創建一個 Provider
這個 Provider 管理 state 並返回一個 contextObject.Provider
組件。
第二步:在 Provider 組件中,使用 props 傳遞 state 和回調函數
export const MContext = React.createContext();
// 導出 context 對象
class MyProvider extends Component {
state = {message: ""}
render() {
return (
<MContext.Provider value={
{
state: this.state,
setMessage: (value) => this.setState({message: value })}}>
{this.props.children} // 這里顯示所有的子組件都可以訪問全局的 store
</MContext.Provider>)
}
}
provider 是所有子組件共享的(一個全局的store,保存了所有 state 和一個操作這些 state 的回調函數)。任何需要這些狀態的組件都需要先和 provider 打交道。
(a) 在 Child1 中通過 provider 中的 setMessage 處理信息
(b) 在 Child2 中通過 provider 獲取信息
第三步:將 MyProvider 當做 Child1 和 Child2 兩個組件的父組件
class App extends React.Component {
render() {
return (
<div>
<MyProvider>
<div className="App">
<Child1/>
<Child2/>
</div>
</MyProvider>
</div>
);
}
}
第四步:Child1 和 Child2 都是 Provider 的消費者,進而都需要通過使用 Consumer 標簽來與 Provider 打交道。
import MContext
class Child1 extends React.Component {
render() {
return (
<div>
<Mcontext.Consumer>
{(context) => (
<button onClick={()=>{context.setMessage("New Arrival")}}>Send</button>
)}
</Mcontext.Consumer>
</div>
)
}
}
Child2 中如何接收這些數據呢?
也是用 Consumer 標簽與 Provider 打交道。
import MContext
class Child2 extends React.Component {
render() {
return (
<div>
<Mcontext.Consumer>
{(context) => (
<p>{context.state.message}}</p>
)}
</Mcontext.Consumer>
</div>
)
}
}
希望上面的描述比較清晰的解釋了如何在 React 中進行大量組件的數據傳遞。
推薦閱讀: