Table of Contents

1、概述

React 的组件逻辑是运行时执行的,因此,我们可以在 React 组件中加入条件判断的逻辑,根据不同的条件,返回不同的 JSX,以渲染不同的内容。

React 组件可以支持所有的 JavaScript 条件判断的逻辑,常用的有:

  • if 语句
  • && 运算符 和 || 运算符
  • 三元运算符 ? :
  • ...

接下来,我们以一个列表清单组件为例,来演示如何使用条件判断的逻辑。

2、清单列表组件

我们要实现一个清单列表的功能,支持展示清单的名称、是否选中、是否删除。如果是选中和删除,会有不同的 UI 样式。

实现的案例效果如下所示:

预览

根据需求,我们可以封装一个 Item 组件来展示每一条清单项。并且需要传入清单的名称、是否选中、是否删除三个属性以供组件内部使用。

code.ts
1
interface InventoryItemProps {
2
name: string,
3
isChecked: boolean,
4
isDelete: boolean,
5
}
6
7
export default function InventoryItem({ name, isChecked, isDelete }: InventoryItemProps) {
8
...
9
}

然后我们考虑前面的选中图标,如果选中,则显示一个对号,否则显示一个方框。此时就非常适合使用条件判断来实现,这里我们使用三元运算符

code.ts
1
const icon = isChecked ? <SquareCheckBig className="w-5 h-5 text-green-600 dark:text-green-400" />
2
: <Square className="w-5 h-5 text-gray-400 dark:text-gray-500" />

当然,也可以使用 if 语句来实现,但是三元运算符更加简洁。

code.ts
1
let icon = null
2
if (isChecked) {
3
icon = <SquareCheckBig className="w-5 h-5 text-green-600 dark:text-green-400" />
4
} else {
5
icon = <Square className="w-5 h-5 text-gray-400 dark:text-gray-500" />
6
}

除此之外,我们注意到,状态不同,UI 的样式也不一样,因此,在 className 上,我们也需要使用条件判断来设置不同的样式。

完整的实现逻辑如下所示

item.tsx
app.tsx
1
import {Square, SquareCheckBig} from 'lucide-react'
2
3
interface InventoryItemProps {
4
name: string,
5
isChecked: boolean,
6
isDelete: boolean,
7
}
8
9
export default function InventoryItem({ name, isChecked, isDelete }: InventoryItemProps) {
10
const icon = isChecked ? <SquareCheckBig className="w-5 h-5 text-green-600 dark:text-green-400" />
11
: <Square className="w-5 h-5 text-gray-400 dark:text-gray-500" />
12
13
return (
14
<div className={`
15
flex items-center gap-3 p-4 rounded-lg border transition-all duration-200
16
${isChecked
17
? 'bg-green-50 border-green-200 dark:bg-green-950/20 dark:border-green-800'
18
: 'bg-white border-gray-200 dark:bg-gray-800 dark:border-gray-700'
19
}
20
${isDelete ? 'opacity-50' : 'opacity-100'}
21
`}>
22
<div className="flex-shrink-0">
23
{icon}
24
</div>
25
<span className={`
26
flex-1 text-sm font-medium
27
${isDelete
28
? 'text-green-800 dark:text-green-200 line-through'
29
: 'text-gray-900 dark:text-gray-100'
30
}
31
`}>
32
{name}
33
</span>
34
</div>
35
)
36
}

3、使用 clsx 库

根据个人习惯的不同。有的时候,我们更习惯于把复杂的条件判断逻辑从 JSX 中单独抽离出来,以确保 JSX 的简洁与可读性。除此之外,过多的代码使用三木运算也会导致可读性的下降。

INFO

这只是个人习惯的侧重,并不是必须的

此时,我们可以使用 clsx 库来优化代码的可读性。重新调整之后,完整的代码如下所示

预览
item.tsx
app.tsx
1
import {Square, SquareCheckBig} from 'lucide-react'
2
import clsx from 'clsx'
3
4
export default function InventoryItem({ name, isChecked, isDelete }: InventoryItemProps) {
5
const cls = clsx(
6
'flex items-center gap-3 p-4 rounded-lg border transition-all duration-200',
7
{
8
'bg-green-50 border-green-200 dark:bg-green-950/20 dark:border-green-800': isChecked,
9
'bg-white border-gray-200 dark:bg-gray-800 dark:border-gray-700': !isChecked,
10
'opacity-50': isDelete,
11
'opacity-100': !isDelete
12
}
13
)
14
15
const spanCls = clsx(
16
'flex-1 text-sm font-medium',
17
{
18
'text-green-800 dark:text-green-200 line-through': isDelete,
19
'text-gray-900 dark:text-gray-100': !isDelete
20
}
21
)
22
23
return (
24
<div className={cls}>
25
<div className="flex-shrink-0">
26
{isChecked ? <SquareCheckBig className="w-5 h-5 text-green-600 dark:text-green-400" /> : <Square className="w-5 h-5 text-gray-400 dark:text-gray-500" />}
27
</div>
28
<span className={spanCls}>
29
{name}
30
</span>
31
</div>
32
)
33
}
34
35
interface InventoryItemProps {
36
name: string,
37
isChecked: boolean,
38
isDelete: boolean,
39
}

4、总结

在 React 中,我们可以使用一切 JavaScript 支持的条件判断,这为 React 组件提供了强大的灵活性支撑。看了完整的案例之后,这里我们再做一个简单的演示。

code.ts
1
if (condition) {
2
// do something
3
return <div>do something</div>
4
} else {
5
// do something
6
return <div>do something</div>
7
}
code.ts
1
// 三元运算符
2
return condition ? <div>do something</div> : <div>do something</div>
code.ts
1
// 范围也可以缩小一点
2
return <div>{condition ? 'do something' : 'do something'}</div>
code.ts
1
// 使用 && 运算符
2
return <div>{condition && <div>do something</div>}</div>
code.ts
1
// 使用 || 运算符
2
return <div>{condition || <div>do something</div>}</div>
专栏首页
到顶
专栏目录