Nowoczesne komponenty generyczne Reacta
Istnieje wiele sposobów na tworzenie komponentów wielokrotnego użytku w React. Począwszy od zbyt dobrze znanej klasy dającej, np: ".button" jako klasy css poprzedzonej ".button-secondary" itd. Ale czy są one odpowiednie dla nowoczesnego Reacta i dużych projektów?
W tym artykule chciałbym przedstawić najlepszą, najbardziej zoptymalizowaną i obecnie znaną mi metodę tworzenia generycznych komponentów na przykładzie przycisku.
W tym konkretnym przykładzie użyłem next.js jako projektu startowego. Do stworzenia naszego projektu będziemy potrzebować kilku bibliotek. Pierwszą z nich będzie dobrze znany TailwindCSS. Jest ona niezbędna do przypisania klas w naszym nowym komponencie generycznym. Następnie musimy stworzyć funkcję pomocniczą o nazwie "cn":
import { clsx } from "clsx"import type { ClassValue } from "clsx";import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs));}
Aby działał poprawnie, z nowym komponentem Button musimy zainstalować następujące elementy: npm i clsx tailwind-merge class-variance-authority
Teraz możemy przystąpić do tworzenia naszego generycznego komponentu Button. Stworzymy go przy użyciu biblioteki "class-variance-authority". Pozwoli nam to tworzyć różne warianty przycisków, do których możemy przypisać klasy TailwindCSS.
import * as React from "react";import { cva } from "class-variance-authority";import type { VariantProps } from "class-variance-authority";
import { cn } from "@/utils/cn";
const buttonVariants = cva( "inline-flex items-center justify-center rounded-md text-base font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", { variants: { variant: { default: "bg-orange-300 text-white hover:bg-orange-400", secondary: "bg-blue-300 text-white hover:bg-blue-400", ghost: "border-orange-300 border-2 roundend-sm text-orange-300 hover:border-blue-400 hover:text-blue-400", }, size: { default: "px-4 py-2", sm: "p-2 text-sm", }, }, defaultVariants: { variant: "default", size: "default", }, });
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {}
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>( ({ className, variant, size, ...props }, ref) => { const Comp = "button"; return ( <Comp className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props} /> ); });Button.displayName = "Button";
export { Button, buttonVariants };
Korzystając z funkcji cva, możemy nadać naszemu komponentowi różne warianty, od "default, secondary, ghost" po bardziej ogólne warianty, takie jak "sizes". Na koniec musimy nadać naszemu komponentowi interfejs dla type-safety. Dzięki temu korzystanie z naszego ogólnego komponentu będzie proste i intuicyjne w całym projekcie.
Ostatni krok obejmuje kwestię wykorzystania naszego nowego komponentu. I jest to banalnie proste. Tutaj wystarczy zaimportować komponent Button z naszego zbudowanego komponentu i jest on gotowy do użycia:
<Button variant="default">Default</Button>
Lub jeśli chcemy użyć innego wariantu:
<Button variant="secondary">Secondary</Button>
Cały kod można znaleźć na moim githubie: https://github.com/shadown125/react-generic-components Jeśli masz jakieś pytania lub opinie, napisz komentarz!
About the author
Penify creator, Fullstack developer, Typescript, Web, Apps, Blogger
I am an experienced Fullstack web developer and the creator of Penify blog platform. I am excited and motivated to explore new technologies. I am a dedicated and hardworking person with a will to create the best user experience.