react-query (useQuery, useMutation)

윱니·2023년 12월 21일

1. 리액트 쿼리에서 mutate 함수를 쓰는 이유

  • 비동기 작업의 결과를 갱신 하고 쿼리의 캐시를 업데이트하여 UI를 갱신하기 위해
  • 업데이트 된 데이터의 실시간 반영이 가능
  • 비동기 작업을 수행하는 경우 비동기 작업이 완료된 후 특정작업을 수행할수 있게 함
import React, { useState } from "react";
import { addTodo } from "../../../api/todos";
import { useMutation, useQueryClient } from "react-query";

function Input() {
  const queryClient = useQueryClient();

  const mutation = useMutation(addTodo, {
    onSuccess: (data) => {
      console.log("data", data);
      queryClient.invalidateQueries("todos");
    },
  });

  const [title, setTitle] = useState("");
  const [contents, setContents] = useState("");

  const handleTitleChange = (event) => {
    setTitle(event.target.value);
  };

  const handleContentsChange = (event) => {
    setContents(event.target.value);
  };

  const handleSubmitButtonClick = async (event) => {
    event.preventDefault();

    // 제목과 내용이 모두 존재해야만 정상처리(하나라도 없는 경우 오류 발생)
    // "01" : 필수 입력값 검증 실패 안내
    if (!title || !contents) {
      return getErrorMsg("01", { title, contents });
    }

    const newTodo = {
      title,
      contents,
      isDone: false,
    };
    mutation.mutate(newTodo);
    setTitle("");
    setContents("");
  };

  return (
    <StyledDiv>
      <form onSubmit={handleSubmitButtonClick}>
        <FlexDiv>
          <RightMarginBox margin={10}>
            <LabledInput
              id="title"
              label="제목"
              placeholder="제목을 입력해주세요."
              value={title}
              onChange={handleTitleChange}
            />
            <HeightBox height={10} />
            <LabledInput
              id="contents"
              label="내용"
              placeholder="내용을 입력해주세요."
              value={contents}
              onChange={handleContentsChange}
            />
          </RightMarginBox>
          <StyledButton type="submit">제출</StyledButton>
        </FlexDiv>
      </form>
    </StyledDiv>
  );
}

export default Input;

=>useMutation 훅을 사용해 addTodo함수 호출

2. mutation 중앙관리하기

  • src > query 폴더를 만듦 -> useTodosQuery.js 파일을 만들어 mutation을 중앙관리
import { useMutation } from "react-query";
import { addTodo, removeTodo, switchTodo } from "../api/todos";

export const useAddmutation = () => useMutation(addTodo);
export const useRemoveMutation = () => useMutation(removeTodo);
export const useSwitchMutation = () => useMutation(switchTodo);

1번에서 작성했던 것을 다음과 같이 리팩토링할 수 있다.

import React, { useState } from "react";
import { useQueryClient } from "react-query";
import { useAddmutation } from "../../../query/useTodosQuery";
import { QUERY_KEYS } from "../../../query/keys.constant";

function Input() {
  const queryClient = useQueryClient();
  const { mutate: addMutate } = useAddmutation();

  const [title, setTitle] = useState("");
  const [contents, setContents] = useState("");

  const handleTitleChange = (event) => {
    setTitle(event.target.value);
  };

  const handleContentsChange = (event) => {
    setContents(event.target.value);
  };

  const handleSubmitButtonClick = async (event) => {
    event.preventDefault();

    // 제목과 내용이 모두 존재해야만 정상처리(하나라도 없는 경우 오류 발생)
    // "01" : 필수 입력값 검증 실패 안내
    if (!title || !contents) {
      return getErrorMsg("01", { title, contents });
    }

    const newTodo = {
      title,
      contents,
      isDone: false,
    };
    
    addMutate(newTodo, {
      onSuccess: (data) => {
        console.log("data", data);
        queryClient.invalidateQueries(QUERY_KEYS.TODOS);
      },
    });
    setTitle("");
    setContents("");
  };

  return (
    <StyledDiv>
      <form onSubmit={handleSubmitButtonClick}>
        <FlexDiv>
          <RightMarginBox margin={10}>
            <LabledInput
              id="title"
              label="제목"
              placeholder="제목을 입력해주세요."
              value={title}
              onChange={handleTitleChange}
            />
            <HeightBox height={10} />
            <LabledInput
              id="contents"
              label="내용"
              placeholder="내용을 입력해주세요."
              value={contents}
              onChange={handleContentsChange}
            />
          </RightMarginBox>
          <StyledButton type="submit">제출</StyledButton>
        </FlexDiv>
      </form>
    </StyledDiv>
  );
}

export default Input;

3. query key 중앙관리하기

  • src > query 폴더를 만듦 -> keys.constant.js 파일을 만들어 query key를 관리
export const QUERY_KEY = {
  TODO: 'todos',
}

=> QUERY_KEY.TODO 를 사용하여 하드 코딩을 방지

profile
코린이 탈출을 기원하는 코린이

0개의 댓글