在撰寫前端頁面時,常常需要根據不同的 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 不接受這種寫法。