在撰寫前端頁面時,常常需要根據不同的 props / state 資料顯示不同的 element。
舉例來說,使用者尚未登入的話要顯示登入按鈕;使用者已經登入的話則顯示登出按鈕。
在這章節中,我們就要來學習如何根據不同的條件 render 出對應的 element。
條件 render 其實沒有任何特殊的語法,它只是 JavaScript 與 JSX 的應用而已。任何 if else expression / statement 的條件判斷方式都可以用來條件 render。
如初探 Component & Props 篇所講,回傳 React element 的 function 就是一個合法的 component,而 component 內要執行哪些邏輯後才回傳 React element 則是開發者可以自由發揮的實作細節。
只要熟悉初探 JSX 與 JSX 語法章節的內容,相信讀者一定能快速掌握條件 render 的精髓。
以下將說明 React 條件 render 的使用方式與常見技巧。這些方法都是可行的條件 Render 處理方式,讀者視可讀性與當下情境應用、延伸、選擇要使用的寫法。
if else
判斷要 render 的 component第一種方法是透過 JavaScript 的 if else
選擇要 render 哪個 element。
承開頭所說的例子。假設我們有一個網頁:
則可以這樣實作:
function LoginButton(props) {
return <button>Login</button>;
}
function LogoutButton(props) {
return <button>Logout</button>;
}
function LoginStatusPanel(props) {
if (props.isLoggedIn) {
return <LogoutButton/>;
}
return <LoginButton/>;
}
ReactDOM.render(
<LoginStatusPanel isLoggedIn={false} />,
document.getElementById('root')
);
可以看到這個範例只是根據不同的情境返回不同的 React element 而已。條件 render 內容如下:
LoginStatusPanel
的 props 內容為 isLoggedIn === true
的話就回傳 <LogoutButton />
React elementLoginStatusPanel
的 props 內容為 isLoggedIn === false
的話則回傳 <LoginButton />
React element第二種方式是把要 render 的 element 判斷好後存在變數中,並在 JSX Expression 中使用這個變數。
讓我們換個做法實作 LoginStatusPanel
:
function LoginButton(props) {
return <button>Login</button>;
}
function LogoutButton(props) {
return <button>Logout</button>;
}
function LoginStatusPanel(props) {
const button = props.isLoggedIn ? <LogoutButton/> : <LoginButton/>
return (
<div>
<h1>Login panel</h1>
{button}
</div>
);
}
範例中,<LoginButton />
與 <LogoutButton />
會根據 props.isLoggedIn
的值判斷完後存到 button
變數中。
isLoggedIn
則 button
內容為 <LogoutButton />
isLoggedIn
則 button
內容為 <LoginButton />
接著在 <div>
中就可以使用 expression:{button}
將判斷好的 element render 到畫面上。
?:
決定 render 哪個 element另外一個方法是直接在 JSX expression 中使用 JavaScript 的三元運算子:?:
來決定要 render 哪個 element。
三元運算子的用法如下:
condition ? exp1 : exp2
就來用 ?:
改寫 LoginStatusPanel
範例吧:
function LoginButton(props) {
return <button>Login</button>;
}
function LogoutButton(props) {
return <button>Logout</button>;
}
function LoginStatusPanel(props) {
return (
<div>
<h1>Login panel</h1>
{ props.isLoggedIn ? <LogoutButton/> : <LoginButton/> }
</div>
);
}
可以看到在 LoginStatusPanel
裡的 expression 中,我們用三元式 ?:
做為條件判斷選擇要 render 哪個 element。
isLoggedIn
加入 <LogoutButton />
到 element 中isLoggedIn
則加入 <LoginButton />
到 element 中&&
決定是否 render element在一些需求下需要讓 component 符合條件就顯示特定 element,而不符合條件就不顯示。我們可以用 expression 中使用 JavaScript 的 && 運算子來達成這件事。
&&
運算子的用法如下:
exp1 && exp2
讓我們來實際演練吧!
現在要實作一個電子郵件 component Mailbox
:
則可以這樣實作:
function Mailbox(props) {
const unreadMessages = props.unreadMessages;
return (<div>
<h1>Hello</h1>
{unreadMessages.length > 0 &&
<h2>You have {unreadMessages.length} unread messages</h2>
}
</div>);
}
範例中:
unreadMessages.length > 0
(代表有未讀信件),會顯示 You have xxx unread messages
unreadMessages.length <= 0
(沒未讀信件),則不會出現任何提示,因為 React 收到 false
就會忽略不 render在一些特定的情形下,我們會希望 component 在條件判斷不成立的時候不要 render 任何 element。
在 React 中,只要讓 component 回傳以下其中一種值即可不 render 任何 element:
null
false
null
以不 render element只要 component 回傳 null
,React 就不會幫該 component render 任何內容。
舉例來說,如果要實作一個網路斷線提示條:NetworkDisconnectedBar
,只在網路斷線的時候顯示。
我們可以用 if
判斷式的方式讓 component 在有網路的狀況下回傳 null
以不顯示任何東西:
function NetworkDisconnectedBar(props) {
if (props.hasNetwork) return null;
return <div>Network disconnected</div>;
}
ReactDOM.render(
<NetworkDisconnectedBar hasNetwork />,
document.getElementById('root')
);
讀者可以到 CodePen 查看結果。
可以看到範例中,因為 props.hasNetwork
為 true
(如果 attribute 沒有 value 的話,其 value 預設值為 true
),使 NetworkDisconnectedBar
回傳 null
,所以畫面不會為 NetworkDisconnectedBar
顯示任何 element。
false
以不 render element同樣的,如果 component 回傳 false
,React 也不會幫該 component render 任何內容。
延續剛剛的 NetworkDisconnectedBar
範例,我們可以應用上面段落學到的 &&
運算子改寫剛剛的程式,讓 component 在有網路的狀況下回傳 false
以不顯示任何東西:
function NetworkDisconnectedBar(props) {
return !props.hasNetwork && <div>Network disconnected</div>;
}
ReactDOM.render(
<NetworkDisconnectedBar hasNetwork />,
document.getElementById('root')
);
讀者可以到 CodePen 查看範例。
可以看到範例中,同樣的,因為 props.hasNetwork
為 true
,使 NetworkDisconnectedBar
回傳 false
,所以畫面不會為 NetworkDisconnectedBar
顯示任何 element。
if else
寫在 JSX Expression 中當筆者剛開始寫 JSX 條件 render 時常常會寫出錯誤的語法:把 if else
寫在 JSX expression 中。
if else
不能夠直接寫在 JSX expression 中,因為 if else
是 statement,而非 expression。
讓我們來做一次錯誤示範:
function LoginButton(props) {
return <button>Login</button>;
}
function LogoutButton(props) {
return <button>Logout</button>;
}
function LoginStatusPanel(props) {
return (
<div>
<h1>Login panel</h1>
{
// Parsing error: Unexpected token if
if (props.isLoggedIn) {
return <LogoutButton/>;
} else {
return <LoginButton/>;
}
}
</div>
);
}
可以看到 expression 中一寫 if
,就會跳出 Parsing error: Unexpected token if
的錯誤。
?小提醒:如何判斷一段程式碼是否為 expression
只要一段程式碼可以被當作參數傳進 function 即代表它是 expression,因為 function 的參數只接受 expression。
如果想要更深入了解 JSX 語法與 expression 的讀者,可以閱讀 JSX 語法篇。
React 中,條件 render 其實就只是 JavaScript 的 if else
與 JSX expression 的應用而已。在本章節中,介紹了一些技巧來做到 React 條件 render 的功能,包括:
if else
判斷要 render 的 component?:
決定 render 哪個 element&&
決定是否 render element這些技巧都是可行的 JSX 條件 Render 處理方式,讀者應視情況應用、延伸、選擇要使用的寫法。
另外我們也學習到了讓 component 不 render 的技巧:
null
false
最後,我們需要避免錯誤的把 if else
寫在 JSX expression 中,因為 if else
是 statement,非 expression,因此 JSX expression 不接受這種寫法。