Conditional Rendering (条件渲染)
React 中, 可以创建封装你需要行为的独特组件。然而,依赖应用能够的状态只能渲染他们中的一部分。
React 条件渲染的运作方式和 JavaScript 中条件分支结构的运作方式相同。使用 JavaScript 条件操作,例如 if 或者
[conditional operator]() 来创建显示当前状态的元素,让 React 更新 UI 来匹配他们。
思考如下两种组件。
function UserGreeting(props) {
return <h1>Welcome back!</h1>;
}
function GuestGreeting(props) {
return <h1>Please sign up.</h1>;
}
Greeting 组件显示依赖于用户是否登录。
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')
);
[在线尝试]()
这个例子依赖于 isLoggedIn prop 的值来渲染不同的内容。
Element 变量
使用 变量存 elements. 这可以通过条件判断渲染组件的部分内容同事其他部分不变。
思考这两个新组件显示 登入登出 按钮
function LoginButton(props) {
return (
<button onClick={props.onClick}>
Login
</button>
);
}
function LogoutButton(props) {
return (
<button onClick={props.onClick}>
Logout
</button>
);
}
下面我们创建一个 [状态化组件]() 称为 LoginControl.
它会根据当前的 state 渲染 <LoginButton /> 或<LogoutButton />中的一种。同时渲染 <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;
if (isLoggedIn) {
button = <LogoutButton onClick={this.handleLogoutClick} />;
} else {
button = <LoginButtong onClick={this.handleLoginClick} />;
}
return (
<div>
<Greeting isLoggedIn={isLoggedIn} />
{button}
</div>
);
}
}
ReactDOM.render(
<LoginControl />,
document.getElementById('root');
);
[在线尝试]()
当声明一个变量使用 if声明是一个好方法来条件话渲染一个组件,有时你可能想要使用更短的预发。
JSX 中行内条件判断的一些方法,下文解释。
行内条件和 逻辑 && 操作符
通过包裹仅花括号的方式可以在[JSX 中嵌入任何表达式]()。这包括 JavaScript 中的 逻辑 && 操作符。这使得根据条件判断是否包含某操作符变得很便利:
function Mailbox(props) {
const unreadMessages = props.unreadMessages;
return (
<div>
<h1>Hello!</h1>
{unreadMessages.length > 0 &&
<h2>
You hava {unreadMessages.length} unread messages.
</h2>
}
</div>
);
}
const messages = ['React', 'Re: React', 'Re:Re:React'];
ReactDOM.render(
<Mailbox unreadMessages={messages} />,
document.getElementById('root')
);
[在线尝试]()
这种方式有效是因为,在 JavaScript 中, true && expression 总是求取 expression 的值, 而且 false && expression 总是求值为 false。
因此,如果条件是 true, 元素正好在 && 之后会出现在输出结果中。如果条件是 false, React 会忽略并跳过它。
行内 If-Else 和条件操作符
另一个条件化行内渲染元素的方法是使用 JavaScript 的条件操作符 codition ? true : false(三目运算)。
下面的例子,我们使用它来条件话渲染一个小的文本块。
render() {
const isLoggedIn = this.state.isLoggedIn;
return (
<div>
The user is <b>{isLoggedIn ? 'currently' : 'not'}</b>
</div>
);
}
当然也可以用来更大的表达式,虽然可读性有些下降:
render() {
const isLoggedIn = this.state.isLoggedIn;
return (
<div>
{isLoggedIn ? (
<LogoutButton onClick={this.handleLogoutClick} />
) : (
<LoginButton onClick={this.handleLoginClick} />
)}
</div>
);
}
就像 JavaScript 中,选择合适的风格基于你和你的团队如何看待更具可读性。无论何时条件变得太复杂,可能是一个好的时机来 [提取组件]()。
阻止组件渲染
特别情况下可能需要隐藏一个组件,即使它被另一个组件渲染了。返回 null 代替它的渲染输出即可。
下面的例子中,<WarningBanner /> 渲染结果依赖 prop称为 warn 的 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')
);
[在线尝试]()
组件的 render 方法返回 null 不影响触发组件的声明周期方法。例如 componentDidUpdate 仍然会被调用。