You need to enable JavaScript to run this app.

Switch Case JSX

Render react components conditionally in the most readable way possible

Usage

<Switch expression={state}>
  <Case value={1}>I'll be rendered if state is 1</Case>
  <Case value={2}>I'll be rendered if state is 2</Case>
  <Case value={3}>I'll be rendered if state is 3</Case>
  <Default>I'll be rendered if state isn't 1, 2, or 3</Default>
</Switch>

Source

import {
  Children,
  isValidElement,
  useEffect,
  useRef,
  type ReactElement,
  type FC,
  type PropsWithChildren,
} from "react";

type ISwitch = FC<PropsWithChildren<{ expression?: unknown }>>;

type ICase = FC<PropsWithChildren<{ value?: unknown }>>;

const Case: ICase = ({ children }) => <>{children}</>;

const Default: FC<PropsWithChildren> = ({ children }) => <>{children}</>;

const Switch: ISwitch = ({ children, expression }) => {
  const matchingCaseRef = useRef<ReactElement>();
  const defaultCaseRef = useRef<ReactElement>();

  useEffect(() => {
    matchingCaseRef.current = undefined;
    defaultCaseRef.current = undefined;
  }, [children]);

  if (!children) return null;

  Children.forEach(children, (child) => {
    if (!isValidElement(child)) return;

    if (!matchingCaseRef.current && child.type === Case) {
      const conditionResult =
        Boolean(expression) ===
        Boolean((child.props as { value: string }).value);

      if (conditionResult) matchingCaseRef.current = child;
    } else if (!defaultCaseRef.current && child.type === Default)
      defaultCaseRef.current = child;
  });

  return matchingCaseRef.current ?? defaultCaseRef.current ?? null;
};

Tests

import { render, screen } from "@testing-library/react";
import { Switch, Case, Default } from "./SwitchCase";

describe("Switch Kit", () => {
  it("renders first matching case", () => {
    render(
      <Switch expression={true}>
        <Case value={true}>Case 1</Case>
        <Case value={true}>Case 2</Case>
      </Switch>
    );

    expect(() => screen.getByText("Case 1")).not.toThrow();
    expect(() => screen.getByText("Case 2")).toThrow();
  });

  it("renders the correct matching case", () => {
    render(
      <Switch expression={true}>
        <Case value={false}>Case 3</Case>
        <Case value={true}>Case 4</Case>
      </Switch>
    );

    expect(() => screen.getByText("Case 3")).toThrow();
    expect(() => screen.getByText("Case 4")).not.toThrow();
  });

  it("renders the default case if there is no matching case provided", () => {
    render(
      <Switch expression={true}>
        <Case value={false}>Falsy Case</Case>
        <Default>Default Case</Default>
      </Switch>
    );

    expect(() => screen.getByText("Falsy Case")).toThrow();
    expect(() => screen.getByText("Default Case")).not.toThrow();
  });

  it("doesn't render the default case if there is a matching case provided", () => {
    render(
      <Switch expression={true}>
        <Case value={true}>Truthy Case</Case>
        <Default>Default Case</Default>
      </Switch>
    );

    expect(() => screen.getByText("Truthy Case")).not.toThrow();
    expect(() => screen.getByText("Default Case")).toThrow();
  });
});
Favourite Books
BooksPoems
Favourite Songs
PlaylistsArtists
Favourite Shows
AnimationsSeriesAnime