在React中,你可以創(chuàng)建不同的組件來(lái)封裝所需的行為。你可以根據(jù)你應(yīng)用的狀態(tài)只渲染其中一部分組件。
React中的條件渲染用起來(lái)和JavaScript中的條件一樣。使用JavaScript操作符:if或條件運(yùn)算符來(lái)創(chuàng)建當(dāng)前狀態(tài)下的元素,從而使React根據(jù)這些元素更新UI。
考慮下面這兩個(gè)組件:
function UserGreeting(props) {
return <h1>Welcome back!</h1>;
}
function GuestGreeting(props) {
return <h1>Please sign up.</h1>;
}
接下來(lái)我們創(chuàng)建一個(gè)Greeting組件,根據(jù)用戶當(dāng)前的登陸狀態(tài)顯示其中一個(gè)組件:
function Greeting(props) {
const isLoggedIn = props.isLoggedIn;
if (isLoggedIn) {
return <UserGreeting />;
}
return <GuestGreeting />;
}
ReactDOM.render(
// Try changing to isLoggedIn={true}:
<Greeting isLoggedIn={false} />,
document.getElementById('root')
);
在CodePen上面試一試
這個(gè)例子根據(jù)prop中的isLoggedIn值來(lái)渲染一個(gè)不同的歡迎信息。
元素變量
你可以使用變量存儲(chǔ)元素。這可以幫助你,在其他輸出部分不變的情況下,有條件的渲染組件的一部分。
看一下這兩個(gè)表示登出和登陸按鈕的新組件:
function LoginButton(props) {
return (
<button onClick={props.onClick}>
Login
</button>
);
}
function LogoutButton(props) {
return (
<button onClick={props.onClick}>
Logout
</button>
);
}
下面的例子中,我們將創(chuàng)建一個(gè)名為LoginControl的狀態(tài)組件。
他會(huì)依據(jù)自己當(dāng)前的狀態(tài),去渲染<LoginButton />或<LogoutButton />。另外它也會(huì)渲染一個(gè)上個(gè)例子中的<Greeting />:
class LoginControl extends React.Component {
constructor(props) {
super(props);
this.handleLoginClick = this.handleLoginClick.bind(this);
this.handleLogoutClick = this.handleLogoutClick.bind(this);
this.state = {isLoggedIn: false};
}
handleLoginClick() {
this.setState({isLoggedIn: true});
}
handleLogoutClick() {
this.setState({isLoggedIn: false});
}
render() {
const isLoggedIn = this.state.isLoggedIn;
let button = null;
if (isLoggedIn) {
button = <LogoutButton onClick={this.handleLogoutClick} />;
} else {
button = <LoginButton onClick={this.handleLoginClick} />;
}
return (
<div>
<Greeting isLoggedIn={isLoggedIn} />
{button}
</div>
);
}
}
ReactDOM.render(
<LoginControl />,
document.getElementById('root')
);
在CodePen上試一試
聲明一個(gè)變量,使用if聲明來(lái)?xiàng)l件化地渲染一個(gè)組件雖然是個(gè)很好的方法,但有時(shí)你也許需要使用一個(gè)更簡(jiǎn)潔的語(yǔ)法。下面我們將介紹,一些JSX中可以做到這點(diǎn)的內(nèi)聯(lián)條件。
使用邏輯操作符&&來(lái)內(nèi)聯(lián)if
你可以將任何表達(dá)式放在花括號(hào)中來(lái)嵌入JSX。這也需要JavaScript的邏輯運(yùn)算符&&來(lái)配合:
function Mailbox(props) {
const unreadMessages = props.unreadMessages;
return (
<div>
<h1>Hello!</h1>
{unreadMessages.length > 0 &&
<h2>
You have {unreadMessages.length} unread messages.
</h2>
}
</div>
);
}
const messages = ['React', 'Re: React', 'Re:Re: React'];
ReactDOM.render(
<Mailbox unreadMessages={messages} />,
document.getElementById('root')
);
在CodePen上試一試
在JavaScript中這是有效的,true && expression始終等價(jià)于expression,false && expression始終等價(jià)于false。
因此,如果條件是true,在&&右邊的元素將會(huì)出現(xiàn)在輸出中。如果是false,React將會(huì)忽略且跳過(guò)它。
使用條件操作符內(nèi)聯(lián)If-Else
另一個(gè)內(nèi)聯(lián)條件化渲染的方法就是使用JavaScript的條件操作符condition ? true : false。
在下面的例子里,我們使用這個(gè)方法來(lái)?xiàng)l件化渲染一小塊文本。
render() {
const isLoggedIn = this.state.isLoggedIn;
return (
<div>
The user is <b>{isLoggedIn ? 'currently' : 'not'}</b> logged in.
</div>
);
}
這也可以用于更大的表達(dá)式,雖然看起來(lái)不太明了:
render() {
const isLoggedIn = this.state.isLoggedIn;
return (
<div>
{isLoggedIn ? (
<LogoutButton onClick={this.handleLogoutClick} />
) : (
<LoginButton onClick={this.handleLoginClick} />
)}
</div>
);
}
就像在JavaScript中一樣,根據(jù)你和你的團(tuán)隊(duì)認(rèn)為哪種更可讀,而去選擇適當(dāng)?shù)娘L(fēng)格。也請(qǐng)記住,當(dāng)條件開(kāi)始變得復(fù)雜了,就意味著該去抽取組件了。
防止組件渲染
極少數(shù)情況,你可能需要組件隱藏自己,即使它由另一個(gè)組件渲染。為此,在渲染輸出中返回null就可以了。
下面的例子中,<WarningBanner />依靠prop中warn的值來(lái)決定是否渲染。如果prop中該值為false,則不渲染該組件:
function WarningBanner(props) {
if (!props.warn) {
return null;
}
return (
<div className="warning">
Warning!
</div>
);
}
class Page extends React.Component {
constructor(props) {
super(props);
this.state = {showWarning: true}
this.handleToggleClick = this.handleToggleClick.bind(this);
}
handleToggleClick() {
this.setState(prevState => ({
showWarning: !prevState.showWarning
}));
}
render() {
return (
<div>
<WarningBanner warn={this.state.showWarning} />
<button onClick={this.handleToggleClick}>
{this.state.showWarning ? 'Hide' : 'Show'}
</button>
</div>
);
}
}
ReactDOM.render(
<Page />,
document.getElementById('root')
);
在CodePen上試一試
組件的render方法返回null不會(huì)影響組件生命周期方法的觸發(fā)。比如,componentWillUpdate和componentDidUpdate依然會(huì)被調(diào)用。