我们在应用程序的任何地方都使用条件,无论是用于状态检查还是根据某些参数将一些数据呈现到视图中。在这篇文章中,我们将展示如何以不同于使用常规 if(...) else {} 块或甚至使用三元条件的方式呈现条件。
例如(1)
type UserType = "admin" | "editor" | "user";
type User = { name: string; type: UserType };
const users: User[] = [
{ name: "john", type: "admin" },
{ name: "mike", type: "editor" },
{ name: "abdelrahman", type: "user" },
];
export default function Test() {
const actions = ["create", "read", "update", "delete"];
return (
<div>
{users.map((user) => (
<div key={user.name}>
{/* we need to render actions depending on user type */}
<p>{user.name}</p>
<div className="flex items-center">
user actions:
{user.type === "admin" && actions.map((a) => <Action a={a} key={a} />)}
{user.type === "editor" && actions.filter((a) => a !== "create").map((a) => <Action a={a} key={a} />)}
{user.type === "user" && actions.filter((a) => a === "read").map((a) => <Action a={a} key={a} />)}
</div>
</div>
))}
</div>
);
}
function Action(props: { a: string }) {
const { a } = props;
return <p className="px-2 py-1 border-[1px] mx-2 rounded-md">{a}</p>;
}
输出示例(1)
在这个例子中,我们必须为每种用户类型制定一个检查条件来呈现他的操作,正如你所看到的,这会消耗大量的代码,更难调试,更难在将来添加更多代码,最后看起来很丑,但这是一个更好的方法
示例(2)
type UserType = "admin" | "editor" | "user";
type User = { name: string; type: UserType };
const users: User[] = [
{ name: "john", type: "admin" },
{ name: "mike", type: "editor" },
{ name: "abdelrahman", type: "user" },
];
const userActionsStates: Record<UserType, string[]> = {
admin: ["create", "read", "update", "delete"],
editor: ["create", "read", "update"],
user: ["read", "update"],
};
export default function Test() {
return (
<div>
{users.map((user) => (
<div key={user.name}>
{/* we need to render actions depending on user type */}
<p>{user.name}</p>
<div className="flex items-center">
user actions:
{userActionsStates[user.type].map((a) => (
<Action key={a} a={a} />
))}
</div>
</div>
))}
</div>
);
}
function Action(props: { a: string }) {
const { a } = props;
return <p className="px-2 py-1 border-[1px] mx-2 rounded-md">{a}</p>;
}
输出示例(2)
输出与示例 (1) 相同
关键变化
将每个用户类型分组到对象键和值中应该是您想要呈现的内容,
在这种情况下,我们传递每个用户类型的操作,如下所示
这里我们不需要像示例 (1) 那样渲染每个条件,也不需要ternary condition
从分组对象中获取用户操作userActionsStates
,只需渲染键值中的任何内容,就完成了,只需要一行代码
那怎么办else
?如果我们传递一个对象中不存在的用户类型怎么办?
在这种情况下,我们可以在对象中添加一个默认键,该键将在
以下情况下使用:
const userActionsStates : Record<UserType , string[] > = {
admin: ["create", "read", "update", "delete"],
editor: ["create", "read", "update"],
user: ["read", "update"],
default : ["read"]
}
如果我们用新用户更新用户,其类型没有像上一个用户对象那样定义
然后我们对 render 方法做一个小小的改动
<div className="flex items-center">
user actions:
{(userActionsStates[user.type] ?? userActionsStates["default"]).map((a) => (
<Action key={a} a={a} />
))}
</div>
使用我们确保它将在 所有条件null coalescing
??
下按预期呈现。:)
请注意
使用此方法,您可以在键的值字符串,数字,数组,组件等中呈现任何内容。
概括
易于阅读、调试和更新🧑💻
看起来很酷😌
更少的代码