>웹 프론트엔드 >JS 튜토리얼 >낙관적 업데이트로 데이터 테이블 구축

낙관적 업데이트로 데이터 테이블 구축

DDD
DDD원래의
2024-11-04 07:28:011034검색

소개

오늘은 최신 React 패턴을 사용하여 세련된 음식 데이터베이스 관리 시스템을 구축한 방법을 공유하겠습니다. TanStack 쿼리(이전의 React 쿼리)의 기능과 Mantine의 구성 요소 라이브러리를 결합하여 원활하고 낙관적인 업데이트로 반응형 데이터 테이블을 생성하는 데 중점을 둘 것입니다.

프로젝트 개요

요구사항

  • 데이터 테이블에 음식 표시
  • 즉시 피드백이 가능한 새 항목 추가
  • 로드 및 오류 상태를 적절하게 처리
  • 부드럽고 긍정적인 업데이트 제공

기술 스택

  • TanStack 쿼리: 서버 상태 관리
  • Mantine UI: 구성 요소 라이브러리 및 양식 관리
  • Mantine React Table: 고급 테이블 기능
  • Wretch: 깔끔한 API 호출
  • TypeScript: 유형 안전성

구현 가이드

1. 재단 설립

먼저 유형과 API 구성을 정의해 보겠습니다.

// Types
export type GetAllFoods = {
  id: number;
  name: string;
  category: string;
};

export type CreateNewFoodType = Pick<
  GetAllFoods,
  | 'name'
  | 'category'
>;

// API Configuration
export const API = wretch('<http://localhost:9999>').options({
  credentials: 'include',
  mode: 'cors',
  headers: {
    'Content-Type': 'application/json',
    Accept: 'application/json',
  },
});

// TANSTACK QUERY 
export const getFoodOptions = () => {
  return queryOptions({
    queryKey: ['all-foods'],
    queryFn: async () => {
      try {
        return await API.get('/foods')
          .unauthorized(() => {
            console.log('Unauthorized');
          })
          .json<Array<GetAllFoods>>();
      } catch (e) {
        console.log({ e });
        throw e;
      }
    },
  });
};

export const useGetAllFoods = () => {
  return useQuery({
    ...getFoodOptions(),
  });
};

2. 데이터 테이블 구축

Mantine React Table을 사용하는 테이블 구성 요소:

const FoodsView = () => {
  const { data } = useGetAllFoods();

  const columns = useMemo<MRT_ColumnDef<GetAllFoods>[]>(
    () => [
      {
        accessorKey: 'id',
        header: 'ID',
      },
      {
        accessorKey: 'name',
        header: 'Name',
      },
      {
        accessorKey: 'category',
        header: 'Category',
      },
      // ... other columns
    ],
    []
  );

  const table = useMantineReactTable({
    columns,
    data: data ?? [],
    // Optimistic update animation
    mantineTableBodyCellProps: ({ row }) => ({
      style: row.original.id < 0 ? {
        animation: 'shimmer-and-pulse 2s infinite',
        background: `linear-gradient(
          110deg,
          transparent 33%,
          rgba(83, 109, 254, 0.2) 50%,
          transparent 67%
        )`,
        backgroundSize: '200% 100%',
        position: 'relative',
      } : undefined,
    }),
  });

  return <MantineReactTable table={table} />;
};

3. 양식 만들기

새로운 음식을 추가하기 위한 양식 구성 요소:

const CreateNewFood = () => {
  const { mutate } = useCreateNewFood();

  const formInputs = [
    { name: 'name', type: 'text' },
    { name: 'category', type: 'text' },
  ];

  const form = useForm<CreateNewFoodType>({
    initialValues: {
      name: '',
      category: '',
      // ... other fields
    },
  });

  return (
    <Box mt="md">
      <form onSubmit={form.onSubmit((data) => mutate(data))}>
        <Flex direction="column" gap="xs">
          {formInputs.map((input) => (
            <TextInput
              key={input.name}
              {...form.getInputProps(input.name)}
              label={input.name}
              tt="uppercase"
              type={input.type}
            />
          ))}
          <Button type="submit" mt="md">
            Create New
          </Button>
        </Flex>
      </form>
    </Box>
  );
};

4. 낙관적 업데이트 구현

구현의 핵심 - 낙관적인 업데이트를 통한 TanStack 쿼리 변형:

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

  return useMutation({
    mutationKey: ['create-new-food'],
    mutationFn: async (data: CreateNewFoodType) => {
      await new Promise(resolve => setTimeout(resolve, 3000)); // Demo delay
      return API.url('/foods').post(data).json<GetAllFoods>();
    },
    onMutate: async (newFood) => {
      // Cancel in-flight queries
      await queryClient.cancelQueries({ queryKey: ['all-foods'] });

      // Snapshot current state
      const previousFoods = queryClient.getQueryData<GetAllFoods[]>(['all-foods']);

      // Create optimistic entry
      const optimisticFood: GetAllFoods = {
        id: -Math.random(),
        ...newFood,
        verified: false,
        createdBy: 0,
        createdAt: new Date().toISOString(),
        updatedAt: new Date().toISOString(),
      };

      // Update cache optimistically
      queryClient.setQueryData(['all-foods'], (old) =>
        old ? [...old, optimisticFood] : [optimisticFood]
      );

      return { previousFoods };
    },
    onError: (err, _, context) => {
      // Rollback on error
      if (context?.previousFoods) {
        queryClient.setQueryData(['all-foods'], context.previousFoods);
      }
    },
    onSettled: () => {
      // Refetch to ensure consistency
      queryClient.invalidateQueries({ queryKey: ['all-foods'] });
    },
  });
};

5. 애니메이션 스타일

낙관적인 업데이트를 생생하게 전달하는 애니메이션:

@keyframes shimmer-and-pulse {
  0% {
    background-position: 200% 0;
    transform: scale(1);
    box-shadow: 0 0 0 0 rgba(83, 109, 254, 0.2);
  }
  50% {
    background-position: -200% 0;
    transform: scale(1.02);
    box-shadow: 0 0 0 10px rgba(83, 109, 254, 0);
  }
  100% {
    background-position: 200% 0;
    transform: scale(1);
    box-shadow: 0 0 0 0 rgba(83, 109, 254, 0);
  }
}

모범 사례

  1. 낙관적인 업데이트
    • 더 나은 UX를 위해 즉시 UI 업데이트
    • 롤백으로 오류 사례 처리
    • 적절한 무효화로 데이터 일관성 유지
  2. 유형 안전
    • 보다 나은 유지 관리를 위해 TypeScript를 사용하세요
    • 데이터 구조에 대한 명확한 인터페이스 정의
    • 가능한 경우 유형 추론을 활용하세요
  3. 공연
    • 업데이트 중 기내 쿼리 취소
    • 올바른 쿼리 무효화 사용
    • 효율적인 양식 상태 관리 구현
  4. 사용자 경험
    • 즉각적인 피드백 제공
    • 로드 상태 표시
    • 오류를 적절하게 처리

향후 개선 사항

구현 시 다음 개선 사항을 고려하세요.

  • 실행 취소/다시 실행 기능
  • 양식 유효성 검사 규칙
  • 오류 경계 구현

결과

Building a Data Table with Optimistic Updates

요청 완료 시

Building a Data Table with Optimistic Updates

결론

이 구현에서는 최신 React 패턴을 사용하여 강력한 데이터 관리 시스템을 만드는 방법을 보여줍니다. TanStack Query, Mantine UI, 사려 깊고 낙관적인 업데이트의 조합은 원활하고 전문적인 사용자 경험을 만들어냅니다.

다음 사항을 기억하세요.

  • 구성요소의 집중성과 유지 관리 가능성을 유지하세요
  • 가능한 모든 상태(로드, 오류, 성공)를 처리합니다
  • 더 나은 코드 품질을 위해 TypeScript를 사용하세요
  • 구현 시 사용자 경험을 고려하세요

React 애플리케이션에서 낙관적인 업데이트를 구현하는 데 어떤 어려움에 직면했습니까? 아래 댓글로 여러분의 경험을 공유해 주세요.

위 내용은 낙관적 업데이트로 데이터 테이블 구축의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.