為什麼要用 Props?

在剛開始學 React 的時候我很喜歡用 Redux 來做狀態集中管理,但是開始工作才發現原來 props 這麼好用。當你的 Components 很簡單只有父與子兩個層級,那麼 props 就是你最好的傳遞資料的好夥伴唷!

什麼是 Props?

Props stand for “Properties.” They are read-only components. Props are also how you pass data from one component to another, as parameters.

簡而言之 Props 有以下幾個特色:

  1. Props 代表了屬性,傳到 Components 內不能做修改,只能讀取
  2. Props 就是在 React Components 間傳遞的參數
  3. 當我們有不只一層 Components 時,Props 就是父層與子層的溝通橋樑

以下圖解兩種比較常用到的傳值方法,分別是父傳子與子傳父。若今天你的 Components 已經包到祖、父、子三個層級的話,就不適用以下的情境圖唷!


Props 在父子傳值時的使用方法

1. 從父傳到子

父傳子

所有的狀態(state)都是在父層做控管,狀態改變後再將結果傳到子層,讓子層因此變化而改變畫面渲染結果。傳到子層時我們可以使用 { } 大括號承接資料,也就是所謂的物件解構賦值。常見的使用情境有 Loading 狀態、表單欄位編輯狀態、欄位必填狀態、API 取回的資料給子層渲染。

EX. 以點擊按鈕改變欄位編輯狀態

如果在父層設有一個按鈕負責控管子層欄位的編輯狀態,點擊後子層的表單從不能編輯變為可以編輯(disabled=true => disabled=false),我們會把 editStatus 直接傳入子層,讓子層重新渲染。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

//父層
const [editableStatus, setEditableStatus] = useState(true);

<button
type="button"
onClick={() => {
setEditableStatus(!editableStatus);
}}>
點我編輯表單
</button>;

<FormComponent editStatus={editStatus}/>

//子層
const FormComponent = ({ editStatus }) => {
<input id="input" type="text" disabled={editStatus} />;
};

export default FormComponent

別忘了監聽變化!

如果子層的值有成功傳入,畫面卻沒有重新渲染,這時候別忘記檢查自己的 component 的 render 狀態有沒有因為新的值傳入而 re-render,大部分的情況都是因為狀態改變,但畫面卻沒有被觸發。


2. 從子傳給父

子傳父

子傳給父的情境,所有的狀態(state)也是在父層做控管,但因為狀態變化是在子層操作的,因此此情境我們會將整個 function 傳入子層,讓子層可以直接操作此 function。而在子層操作此 function 後再將 output Value 傳回父層。常見的情境是使用者在子層輸入值後,將此值傳入父層並呼叫 Post API。

EX. Input 欄位輸入值,並將值回傳 API

在子層有一 Input 欄位,使用者輸入數值後,我們把數值透過 function 傳回父層,讓父層可以取得此數值,並進一步將此數值傳給後端。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

//父層
const [data, setData] = useState([]);

const handleSubmitData = () => {
uploadDataAPI(data);
};

<FormComponent setData={setData}/>

//子層
const FormComponent = ({ setData }) => {
<input
id="input"
type="number"
onChange={(event) => {
setData(event.target.value);
}}
/>;
};

export default FormComponent;

這兩種就是平常開發最常用的 props 傳值情境,希望圖解有幫助到大家,我也是多實作幾次才更能理解這些情境,菜鳥的路不簡單,我們一起繼續努力。