일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- EnhancedFor
- 오라클
- 추상메서드
- exception
- 한국건설관리시스템
- 제네릭
- 메소드오버로딩
- cursor문
- Java
- 대덕인재개발원
- 인터페이스
- 컬렉션 타입
- 환경설정
- 집합_SET
- 예외처리
- 컬렉션프레임워크
- NestedFor
- 사용자예외클래스생성
- GRANT VIEW
- 어윈 사용법
- 참조형변수
- 예외미루기
- 다형성
- 자바
- abstract
- 정수형타입
- 생성자오버로드
- 자동차수리시스템
- 객체 비교
- oracle
- Today
- Total
거니의 velog
(51) 리액트 쿼리와 리코일 3 본문
3. 상품등록 처리
* 리액트 쿼리에서 가장 중요한 기능은 useQuery()와 useMutation() 이다. SQL로 비유하자면 useQuery()가 select를 위해서 사용된다면, useMutation()은 insert/update/delete를 위해서 사용된다. useMutation() 은 파라미터로 서버를 호출하는 함수를 전달하고 mutate()를 이용해서 처리 결과에 대한 다양한 정보를 얻을 수 있다.
* 상품등록 기능을 처리하는 components/products/AddComponent.js를 수정한다.
* AddComponent에 useMutation()이 적용되므로 모달창을 처리하기 위한 fetching이나 result와 관련된 내용들을 모두 삭제하고 useMutation()을 적용한다.
import React, { useRef, useState } from "react";
import { postAdd } from "../../api/productsApi";
import FetchingModal from "../common/FetchingModal";
import ResultModal from "../common/ResultModal";
import useCustomMove from "../../hooks/useCustomMove";
import { useMutation } from "@tanstack/react-query";
const initState = {
pname: "",
pdesc: "",
price: 0,
files: [],
};
const AddComponent = () => {
// 기본적으로 필요
const [product, setProduct] = useState({ ...initState });
const uploadRef = useRef();
const { moveToList } = useCustomMove();
// 입력값 처리
const handleChangeProduct = (e) => {
product[e.target.name] = e.target.value;
setProduct({ ...product });
};
const addMutation = useMutation((product) => postAdd(product)); // 리액트 쿼리
const handleClickAdd = (e) => {
const files = uploadRef.current.files;
const formData = new FormData();
for (let i = 0; i < files.length; i++) {
formData.append("files", files[i]);
}
//other data
formData.append("pname", product.pname);
formData.append("pdesc", product.pdesc);
formData.append("price", product.price);
addMutation.mutate(formData); // 기존 코드에서 변경
};
const closeModal = () => {
moveToList({ page: 1 }); // 모달 창이 닫히면 페이지로 이동
};
return (
<div className="border-2 border-sky-200 mt-10 m-2 p-4">
{/* 생략 모달 창들은 잠시 삭제
{fetching ? <FetchingModal /> : <></>}
{result ? (
<ResultModal
title={"Product Add Result"}
content={`${result}번 등록 완료`}
callbackFn={closeModal}
/>
) : (
<></>
)}
*/}
(...)
</div>
);
};
export default AddComponent;
* 변경된 코드를 실행하면 새로운 상품이 등록되기는 하지만 화면상에 변화는 없으므로 직접 목록 페이지로 이동해서 결과를 확인한다.
(1) useMutation()의 반환값
* useMutation()의 반환값들은 'isXXX'와 'data, error'와 같은 실제 결과 데이터들이다. 기존의 예제와 같이 FetchingModal과 ResultModal을 보이도록 코드를 수정해 보자.
return (
<div className="border-2 border-sky-200 mt-10 m-2 p-4">
{addMutation.isLoading ? <FetchingModal /> : <></>}
{addMutation.isSuccess ? (
<ResultModal
title={"Product Add Result"}
content={`Product Add Success ${addMutation.data.result}`}
callbackFn={closeModal}
/>
) : (
<></>
)}
(...)
* 브라우저에서 새로운 상품을 등록하면 처리 중인 경우와 처리 후 모달창이 보이게 된다.
[등록 후 처리 invalidateQueries()]
* 목록 화면에서 사용하는 useQuery()의 staleTime이 짧은 경우에는 문제가 되지 않겠지만, staleTime이 긴 경우에는 새로운 상품을 등록해도 목록으로 이동한 경우에 서버를 호출하지 않기 때문에 기존 페이지가 그대로 유지되는 현상이 생길 수 있다.
* 예를 들어 ListComponent에서 staleTime을 1분으로 지정하고 새로운 상품을 추가하면?
const ListComponent = () => {
const { page, size, moveToList, moveToRead, refresh } = useCustomMove();
const { moveToLoginReturn } = useCustomLogin();
const { isFetching, data, error, isError } = useQuery(
["products/list", { page, size, refresh }], // refresh 추가
() => getList({ page, size }),
{ staleTime: 1000 * 5 * 12 } // staleTime 추가
);
* 125번으로 새로운 상품이 등록되었고, 모달창을 닫아서 목록 화면으로 이동하게 되는데 이 경우 125번 상품은 아직 보이지 않고 124번까지만 보이는 것을 확인할 수 있다.
* 이를 해결하기 위해서는 AddComponent에서 모달창을 닫을 때 invalidateQueries()를 호출해야 한다.
import React, { useRef, useState } from "react";
import { postAdd } from "../../api/productsApi";
import FetchingModal from "../common/FetchingModal";
import ResultModal from "../common/ResultModal";
import useCustomMove from "../../hooks/useCustomMove";
import { useMutation, useQueryClient } from "@tanstack/react-query";
(...)
const AddComponent = () => {
(...)
const queryClient = useQueryClient();
const closeModal = () => {
queryClient.invalidateQueries("products/list");
moveToList({ page: 1 }); // 모달 창이 닫히면 페이지로 이동
};
return (
<div className="border-2 border-sky-200 mt-10 m-2 p-4">
(...)
</div>
);
};
export default AddComponent;
* 변경된 코드를 이용하면 새로운 상품이 등록된 후에 기존 상품 목록 데이터들이 invalidate되기 때문에 다시 서버를 호출해서 방금 추가된 상품이 목록에 출력되는 것을 확인할 수 있다.
'SpringBoot_React 풀스택 프로젝트' 카테고리의 다른 글
(53) 리액트 쿼리와 리코일 5 (0) | 2024.03.11 |
---|---|
(52) 리액트 쿼리와 리코일 4 (0) | 2024.03.11 |
(50) 리액트 쿼리와 리코일 2 (0) | 2024.03.11 |
(49) 리액트 쿼리와 리코일 1 (0) | 2024.03.11 |
(48) 리액트 장바구니 구성 3 (0) | 2024.03.11 |