> 웹 프론트엔드 > JS 튜토리얼 > 반응 양식, zod, 반응 데이터 그리드, 반응 쿼리 및 json-server를 사용하여 CRUD 앱 구축

반응 양식, zod, 반응 데이터 그리드, 반응 쿼리 및 json-server를 사용하여 CRUD 앱 구축

Linda Hamilton
풀어 주다: 2024-11-24 19:14:10
원래의
611명이 탐색했습니다.

목표 :

우리의 목표는 React CRUD 애플리케이션을 개발하는 것입니다.

Building CRUD App with react-form, zod, react data grid, react-query and json-server

저희 스택 :

  • 반응형
  • 조드
  • 애그그리드 반응
  • 반응 쿼리
  • json-서버

설치 환경 :

vite를 사용하여 반응 프로젝트 만들기:

npm create vite@latest crud-react -- --template react-ts
로그인 후 복사

종속성 설치:

npm install react-hook-form zod @hookform/resolvers ag-grid-react react-query axios
로그인 후 복사

서버 생성 및 시작:

객체(제품) 구조 :

{
    "id": "w38y",
    "name": "Vitamin C Tablets",
    "price": 19.99,
    "expiryDate": "2025-01-01",
    "emailSupplier": "contact@healthplus.com"
}
로그인 후 복사

/db/db.json에 샘플 데이터가 포함된 파일을 만듭니다.

{
  "products": [
    {
      "id": "w38y",
      "name": "Vitamin C Tablets",
      "price": 19.99,
      "expiryDate": "2025-01-01",
      "emailSupplier": "contact@healthplus.com"
    },
    {
      "id": "a99x",
      "name": "Omega-3 Fish Oil",
      "price": 30.99,
      "expiryDate": "2024-11-15",
      "emailSupplier": "support@nutricore.com"
    },
    {
      "id": "x82j",
      "name": "Calcium + Vitamin D",
      "price": 15.5,
      "expiryDate": "2026-06-01",
      "emailSupplier": "orders@welllifelabs.com"
    },
    {
      "id": "a40i",
      "name": "Zinc Lozenges",
      "price": 12.99,
      "expiryDate": "2024-09-30",
      "emailSupplier": "sales@herbalessentials.com"
    },
    {
      "id": "c52f",
      "name": "Probiotic Capsules",
      "price": 25.75,
      "expiryDate": "2025-03-20",
      "emailSupplier": "info@guthealthlabs.com"
    }
  ]
}
로그인 후 복사

json-server 시작:

npx json-server db/db.json
로그인 후 복사

반응 쿼리 설정 :

/src/App.tsx 업데이트:

import { QueryClient, QueryClientProvider } from "react-query";

const queryClient = new QueryClient();

function App() {
  return (
    <QueryClientProvider client={queryClient}>
    </QueryClientProvider>
  );
}

export default App;
로그인 후 복사

/src/types.ts 생성:

export type FormData = {
  name: string;
  price: number;
  expiryDate: string;
  emailSupplier: string;
};

export type FormFieldNames = "name" | "price" | "expiryDate" | "emailSupplier";  

export type Product = {
  id: string;
  name: string;
  price: number;
  expiryDate: string;
  emailSupplier: string;
};
로그인 후 복사

/src/server/productQuery.ts 생성:

import { useMutation, useQuery, useQueryClient } from "react-query";
import { FormData, Product } from "../types";
import axios from "axios";

const URL = "http://localhost:3000";
const PRODUCTS = "products";

export const save = async (product: FormData) =>
  axios.post(`${URL}/${PRODUCTS}`, product);

export const useSave = () => {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: (newProduct: FormData) => save(newProduct),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: [PRODUCTS] });
    },
  });
};

export const fetch = async () => {
  const result = await axios.get(`${URL}/${PRODUCTS}`);
  return result.data;
};

export const useProducts = () =>
  useQuery<Product[]>({
    queryKey: [PRODUCTS],
    queryFn: fetch,
  });

const remove = async (id: string) => {
  await axios.delete(`${URL}/${PRODUCTS}/${id}`);
};

export const useRemove = () => {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: (id: string) => remove(id),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: [PRODUCTS] });
    },
  });
};

export const update = async (product: Product) =>
  axios.put(`${URL}/${PRODUCTS}/${product.id}`, product);

export const useUpdate = () => {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: (product: Product) => update(product),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: [PRODUCTS] });
    },
  });
};
로그인 후 복사

양식 만들기:

/src/types.ts 업데이트:

import { z, ZodType } from "zod";

export type FormData = {
  name: string;
  price: number;
  expiryDate: string;
  emailSupplier: string;
};

export type FormFieldNames = "name" | "price" | "expiryDate" | "emailSupplier";

export const ProductSchema: ZodType<FormData> = z.object({
  name: z.string().min(3),
  price: z.number().min(1).max(1000),
  expiryDate: z
    .string()
    .refine(
      (date) => new Date(date) > new Date(),
      "Expiry Date must be superior than current date",
    ),
  emailSupplier: z.string().email(),
});



export type Product = {
  id: string;
  name: string;
  price: number;
  expiryDate: string;
  emailSupplier: string;
};
로그인 후 복사

/src/comComponents/form/FormField.tsx 생성:

import { FieldError, UseFormRegister } from "react-hook-form";
import { FormData, FormFieldNames } from "../../types";

type FormFieldProps = {
  type: string;
  placeholder: string;
  name: FormFieldNames;
  register: UseFormRegister<FormData>;
  error: FieldError | undefined;
  valueAsNumber?: boolean;
  step?: number | string;
};

const FormField = ({
  type,
  placeholder,
  name,
  register,
  error,
  valueAsNumber,
  step,
}: FormFieldProps) => (
  <>
    <input
      type={type}
      placeholder={placeholder}
      step={step}
      {...register(name, { valueAsNumber })}
    />
    {error && <span> {error.message} </span>}
  </>
);

export default FormField;
로그인 후 복사

/src/comComponents/form/Form.tsx 생성:

import { useForm } from "react-hook-form";
import FormField from "./FormField";
import { FormData, ProductSchema } from "../../types";
import { zodResolver } from "@hookform/resolvers/zod";
import { useSave } from "../../server/productQuery";

const Form = () => {
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm<FormData>({
    resolver: zodResolver(ProductSchema),
  });

  const mutation = useSave();

  const onSubmit = (data: FormData) => {
    mutation.mutate(data);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <div>
        <FormField
          type="text"
          placeholder="Name"
          name="name"
          register={register}
          error={errors.name}
        />
        <FormField
          type="number"
          placeholder="Price"
          name="price"
          step="0.01"
          register={register}
          error={errors.price}
          valueAsNumber
        />
        <FormField
          type="date"
          placeholder="Expiry Date"
          name="expiryDate"
          register={register}
          error={errors.expiryDate}
        />

        <FormField
          type="email"
          placeholder="Email"
          name="emailSupplier"
          register={register}
          error={errors.emailSupplier}
        />
        <button type="submit">Add</button>
      </div>
    </form>
  );
};

export default Form;
로그인 후 복사

테이블 생성:

/src/comComponents/table/Products.tsx 생성:

import { useMemo } from "react";
import { Product } from "../../types";
import { useProducts, useRemove, useUpdate } from "../../server/productQuery";

import { AgGridReact } from "ag-grid-react";
import { ColDef, ColGroupDef } from "ag-grid-community";
import "ag-grid-community/styles/ag-grid.css";
import "ag-grid-community/styles/ag-theme-quartz.css";

const Products = () => {
  const { data: products } = useProducts();
  const removeMutation = useRemove();
  const updateMutation = useUpdate();

  const columns = useMemo<(ColDef | ColGroupDef<Product>)[]>(
    () => [
      { field: "id", editable: false },
      { field: "name", editable: true },
      { field: "price", editable: true },
      { field: "expiryDate", editable: true },
      { field: "emailSupplier", editable: true },
      {
        field: "delete",
        sortable: false,
        editable: false,
        cellRenderer: (params: { data: Product }) => (
          <button onClick={() => removeMutation.mutate(params.data.id)}>
            Delete
          </button>
        ),
      },
    ],
    [],
  );

  return (
    <div className="ag-theme-quartz">



<p>Update /src/App.tsx :<br>
</p>

<pre class="brush:php;toolbar:false">import { QueryClient, QueryClientProvider } from "react-query";
import Form from "./components/form/Form";
import Products from "./components/table/Products";

const queryClient = new QueryClient();

function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <Form />
      <Products />
    </QueryClientProvider>
  );
}

export default App;
로그인 후 복사

힘내 저장소:

https://github.com/TesMae/crud-react

따라와주셔서 감사합니다!

위 내용은 반응 양식, zod, 반응 데이터 그리드, 반응 쿼리 및 json-server를 사용하여 CRUD 앱 구축의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:dev.to
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿