如何写好条件渲染
jsx 中编写条件渲染,很多人往往使用三元运算符号,当条件复杂时,三元运算符会难以阅读,导致我们的 jsx 也难以阅读。
今天就来谈谈有哪些方式写出干净的、可读性好的条件渲染。
提前返回
jsx
function ListPage() {
const { data, error, isLoading } = useGetData()
if (isLoading) {
return (
<Layout>
<LoadingSpinner />
</Layout>
)
}
if (error) {
return (
<Layout>
<ErrorMessage message={error.message} />
</Layout>
)
}
return (
<Layout>
{data.items.map(item => (
<Item key={item.id} item={item} />
))}
</Layout>
)
}
Layout
重复:
jsx
function ListPage() {
const { data, isLoading } = useGetData()
if (isLoading) {
return (
<Layout>
<LoadingSpinner />
<MoreComponents>
{
//... more components here
}
</MoreComponents>
</Layout>
)
}
return (
<Layout>
{data.items.map(item => (
<Item key={item.id} item={item} />
))}
<MoreComponents>
{
//... more components here
}
</MoreComponents>
</Layout>
)
}
MoreComponents
还是重复,继续优化:
jsx
export function ItemList() {
const { data, error, isLoading } = useGetData()
if (isLoading) {
return <LoadingSpinner />
}
return data.items.map(item => <Item key={item.id} item={item} />)
}
export function ListPage() {
return (
<Layout>
<ItemList />
<MoreComponents>
{
//... more components here
}
</MoreComponents>
</Layout>
)
}
返回 null
jsx
export function ItemList({ items }) {
return items.map(item => <Item key={item.id} item={item} />)
}
function ListPage() {
const { data } = useGetData()
return <Layout>{!!data?.items && <ItemList items={data.items} />}</Layout>
}
ListPage 可读性还是不高,继续优化:
jsx
export function ItemList({ items }) {
if (!items) {
return null
}
return items.map(item => <Item key={item.id} item={item} />)
}
function ListPage() {
const { data } = useGetData()
return (
<Layout>
<ItemList items={data?.items} />
</Layout>
)
}
再优化:
jsx
export function ItemList({ isHidden }) {
const { data } = useGetData()
if (isHidden) {
return null
}
return data.items.map(item => <Item key={item.id} item={item} />)
}
function ListPage({ isItemListHidden }) {
return (
<Layout>
<ItemList isHidden={isItemListHidden} />
</Layout>
)
}
可选链操作符
jsx
function ListPage() {
// data.tags may be null or undefined
const { data } = useGetData()
return (
<Layout>
<Post post={data.post} />
{data.tags?.map(tag => (
<Tag key={tag.id} tags={tag} />
))}
</Layout>
)
}
渲染变量
jsx
function ListPage() {
const { data, isLoading } = useGetData()
let content = <LoadingSpinner />
if (!isLoading) content = data.items.map(item => <Item key={item.id} item={item} />)
return <Layout>{content}</Layout>
}
三元操作符结合变量:
jsx
function ListPage() {
const { data, isLoading } = useGetData()
const content = isLoading ? <LoadingSpinner /> : data.items.map(item => <Item key={item.id} item={item} />)
return <Layout>{content}</Layout>
}
component map / 枚举
jsx
const components = {
loading: <LoadingSpinner />,
error: <ErrorMessage />,
success: <ItemList />,
}
function ListPage() {
const { status } = useGetData()
return <Layout>{components[status]}</Layout>
}
传递参数:
jsx
const components = {
loading: () => <LoadingSpinner />,
error: ({ error }) => <ErrorMessage message={error.message} />,
success: ({ data }) => <ItemList items={data.items} />,
}
function ListPage() {
const { data, error, status } = useGetData()
return <Layout>{components[status]({ data, error })}</Layout>
}
参考
Conditional Rendering In React With A Focus On Readability And Clean Code