React 中的条件渲染有以下几种方式:
在React中使用if语句条件渲染是最简单的。比如List组件如果没有任何items,可以提前return
function List({ list }) {
if (!list) {
return null;
}
return (
{list.map(item => )}
);
}
一个组件如果return null
,将不会被渲染出来。如果你想给用户一些反馈,当list为空时,可以采用下面方式:
function List({ list }) {
// list 为null的情况
if (!list) {
return null;
}
// list 为空的情况
if (!list.length) {
return sorry, the list is empty
} else {
return (
{list.map(item => )}
);
}
}
if...else 是最基本的条件渲染方式。
可以使用三元运算符来代替上面的if...else...
条件渲染。
例如,你想从2种模式(edit, view)中切换,可以使用布尔值来决定那个组件被渲染:
function Item({ item, mode }) {
const isEditMode = mode === 'EDIT';
return (
{ isEditMode
?
:
}
);
}
三元运算符使条件渲染更加的简洁,使得代码可以采用内联(inline)的方式表达出来
这个是当你想渲染一个组件或者什么也不渲染的情况。
例如,有一个 LoadingIndicator
组件,返回加载文字或者什么也没有。当然可以使用if...else或者三元运算符,如下:
function LoadingIndicator({ isLoading }) {
if (isLoading) {
return (
Loading...
);
} else {
return null;
}
}
function LoadingIndicator({ isLoading }) {
return (
{ isLoading
? Loading...
: null
}
);
}
使用 &&
可以使返回 null 的情况的条件渲染更加的简洁:
function LoadingIndicator({ isLoading }) {
return (
{ isLoading && Loading...
}
);
}
我们有可能遇到多种条件渲染的情况,例如依据不同的state渲染不同的Component.
例如,Notification 组件根据输入状态可能渲染Error,Warning,Info三种不同的组件。这个时候可以使用switch...case来进行多种条件渲染:
function Notification({ text, state }) {
switch (state) {
case 'info':
return ;
case 'warning':
return ;
case 'info':
return ;
default:
return null;
}
}
注意switch...case语句永远要加上default情况,因为React组件要么返回元素,要么返回null
另外值得注意的是,如果组件依据 state 属性 渲染时,最后添加上 React.PropTypes,即上面的组件后面添加:
Notification.propTypes = {
text: React.PropTypes.string,
state: React.PropTypes.oneOf(['info', 'warning', 'error'])
}
另一种将条件渲染结果内联在switch...case中的方法是,使用立即调用函数
function Notification({ text, state }) {
return (
{(() => {
switch (state) {
case 'info':
return ;
case 'warning':
return ;
case 'info':
return ;
default:
return null;
}
})()}
);
}
switch...case
帮助我们在多种条件中渲染中使用,但是多种条件渲染最好的方式是枚举
在javascript中,对象的键值对可以用作枚举:
const ENUM = {
a: '1',
b: '2',
c: '3'
};
枚举是多种条件渲染中很好的一种方式,上面的 Notification 组件可以写为:
function Notification({ text, state }) {
return (
{{
info: ,
warning: ,
error:
}[state]}
)
}
上面的 state 属性用于取回对象中的值,这比switch...case可读性更强。
因为对象的值依赖 text
属性,所以我们必须使用内联对象。如果我们不需要text属性,我们可以使用外部静态枚举:
const NOTIFICATION_STATES = {
info: ,
warning: ,
error: ,
};
function Notification({ state }) {
return (
{NOTIFICATION_STATES[state]}
)
}
如果我们需要text属性,我们可以使用函数取回对象的值
const getSpecificNotification = (text) => ({
info: ,
warning: ,
error: ,
});
function Notification({ state, text }) {
return (
{getSpecificNotification(text)[state]}
)
}
对象用作枚举,使用场景很灵活,下面例子:
function FooBarOrFooOrBar({ isFoo, isBar }) {
const key = `${isFoo}-${isBar}`;
return (
{{
['true-true']: ,
['true-false']: ,
['false-true']: ,
['false-false']: null,
}[key]}
);
}
FooBarOrFooOrBar.propTypes = {
isFoo: React.PropTypes.boolean.isRequired,
isBar: React.PropTypes.boolean.isRequired
}
我们有时候可能碰到嵌套条件选择渲染的情况。
例如,List组件可能显示一个list,或者一个empty text提示,或者什么多没有:
function List({ list }) {
const isNull = !list;
const isEmpty = !isNull && !list.length;
return (
{ isNull
? null
: ( isEmpty
? Sorry, the list is empty
: {list.map(item => )}
)
}
);
}
// 实例
//
// Sorry, the list is empty
// abc
但是最好保持嵌套的层数最小化,这样代码可读性更强。可以将组件划分成更小的组件的方式
function List({ list }) {
const isList = list && list.length;
return (
{ isList
? {list.map(item => )}
:
}
);
}
function NoList({ isNull, isEmpty }) {
return (!isNull && isEmpty) && Sorry, the list is empty
}
HOCs 在React中很适合条件渲染。HOCs的一种使用方式就是改变组件的外观。
例如使用高阶组件来展示一个加载显示器或者一个想要的组件:
function withLoadingIndicator(Component) {
return function EnhancedComponent({ isLoading, ...props }) {
if (!isLoading) {
return ;
}
return Loading...
;
}
}
// 使用
const ListWithLoadingIndicator = withLoadingIndicator(List);
这个示例中,List组件能关注渲染list上,而不必担心loading状态,另外,HOCs可以屏蔽list为null或empty的情况。
使用上面的哪一种条件渲染可以根据下面的一些情况而定:
if-else
三元操作符
逻辑 '&&' 操作符
switch...case
枚举(enums)
多层次条件选择渲染
HOCs