发布于 2025-03-16 26 阅读
0

停止渲染这样的条件

我们在应用程序的任何地方都使用条件,无论是用于状态检查还是根据某些参数将一些数据呈现到视图中。在这篇文章中,我们将展示如何以不同于使用常规 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 ??下按预期呈现。:)

更新用户输出

请注意

使用此方法,您可以在键的值字符串,数字,数组,组件等中呈现任何内容。

概括

  • 易于阅读、调试和更新🧑‍💻

  • 看起来很酷😌

  • 更少的代码

这取决于你的创造力和想象力💡🔥