React-Query 알아보기(2)

이지훈·2022년 10월 31일
0
post-thumbnail

우선 저번 포스팅에서 React-query의 기초에 대해서 알아보았다.
저번 시간에 설명하고 넘어가지 않았던것을 정리하고 react-query를 마무리 지어보고자 한다.

우선 마지막에 발생되었던 NextJs에서 suspense를 사용할때 발생되었던 문제는 결국 실패하였다.
그 원인으로는
1. react-query가 ssr을 지원하지 않는다.
2. 내가 쓴 NextJs의 버전은 12버전이였다. 하지마 12버전은 suspense를 정식으로 지원하지 않는다.(단, 13버전에서는 정식 지원을 한다고 하는데 조금더 지켜봐야 할것 같다.)
-> 따라서 NextJs에서 react-query를 쓴다면 그냥 isLoading를 이용해서 로딩화면을 구현해야 할것 같다.
혹시나 방법이 아시는분이 있으시면 댓글로 꼭 도와주세요😂

UseQuery를 동기적으로

먼저 한개의 api를 더 불러와야하기 때문에 NestJs를 이용해 Get Api를 하나 더 만든뒤 api 호출 함수도 제작한다.

export const fetchJobData = async () => {
    const url = `http://localhost:4000/job`;

    const res = await axios({
        method: "get",
        url,
    });

    return res.data;
};

저번 포스팅에서도 다뤘듯이 usequery는 비동기적으로 동작을 한다. 즉, 동기적으로 하기위해서는 다음과 같은 과정을 거쳐야 한다.
동기적 처리를 안했을 때 화면

다음과 같이 두개의 usequery가 동시에 불러와지는것을 볼수 있다.

enabled 속성 사용코드

// index.tsx

const Home: NextPage = () => {
    const { isLoading: firstLoading, data: firstData } = useQuery<ExamType>(
        "exam",
        fetData,
        {
            refetchOnWindowFocus: false,
            retry: 0,
        },
    );

    const { isLoading: jobLoading, data: jobData } = useQuery<ExamType2>(
        "job",
        fetchJobData,
        {
            refetchOnWindowFocus: false,
            retry: 0,
            enabled: !!firstData, 
            //enabled 속성을 이용하여 firstData가 생기면 실행이되도록 한다.
        },
    );

    const putEmail = useMutation(putData, {
        onSettled: () => {
            console.log("end");
        },
        onSuccess: (data) => {
            queryClient.invalidateQueries("exam");
        },
    });

    return (
        <div>
            <Head>
                <title>Create Next App</title>
                <meta
                    name="description"
                    content="Generated by create next app"
                />
                <link rel="icon" href="/favicon.ico" />
            </Head>
            {firstLoading ? <Loading seq="first" /> : <Exam data={firstData} />}
            <button
                onClick={() => {
                    putEmail.mutate();
                }}>
                email 변경
            </button>
            {jobLoading ? <Loading seq="job" /> : <Exam2 data={jobData} />}
        </div>
    );
};

enabled 실행화면

다음과 같이 data를 fetching한 후에 다음 useQuery를 실행하는것을 확인 할 수 있다.

UseQueries

Js의 Promise.all, axios.all 처럼 하나로 묶어서 사용 할 수 있는 기술이다. 동기적이다 뭐다 귀찮을때 한번에 때려 밖는 기술이다.
실행 코드

const Home: NextPage = () => {
    const result = useQueries([
        {
            queryKey: "exam",
            queryFn: fetData,
            refetchOnWindowFocus: false,
            retry: 0,
        },
        {
            queryKey: "job",
            queryFn: fetchJobData,
            refetchOnWindowFocus: false,
            retry: 0,
        },
    ]);

    const putEmail = useMutation(putData, {
        onSettled: () => {
            console.log("end");
        },
        onSuccess: (data) => {
            queryClient.invalidateQueries("exam");
        },
    });

    return (
        <div>
            <Head>
                <title>Create Next App</title>
                <meta
                    name="description"
                    content="Generated by create next app"
                />
                <link rel="icon" href="/favicon.ico" />
            </Head>
            {!result[0].isLoading && result?.length > 0 ? (
                <Exam data={result[0].data} />
            ) : (
                <Loading seq="first" />
            )}
            <button
                onClick={() => {
                    putEmail.mutate();
                }}>
                email 변경
            </button>
            {!result[1].isLoading && result?.length > 1 ? (
                <Exam2 data={result[1].data} />
            ) : (
                <Loading seq="job" />
            )}
        </div>
    );
};

실행 화면

실행화면을 보면 알겠지만 그냥 useQuery를 여러개 쓰는거랑 똑같은 결과가 발생한다. 즉, 그냥 useQuery를 여러개 쓰기 실을때 쓰거나 배열으 이용해서 api를 호출 할때 주로 사용되어 진다.

Unique Key

useQuery의 첫번재 parameter는 string으로 이루어진 배열이다. 첫번째 요소는 key이고 두번째 요소가 바로 unique key이다.
이 unique key는 api 호출함수에 값을 전달해줄때 사용되어 진다.
우선 NestJs에서 parmeter를 필요로 하는 Get Api를 하나 만들고, 그에따른 api 호출 함수를 만든다.

export const fetchOneUser = async (id: any) => {
    const url = `http://localhost:4000/${id}`;

    const res = await axios({
        method: "get",
        url,
    });

    return res.data;
};

unique key 사용 코드

const Home: NextPage = () => {
    const { isLoading: firstLoading, data: firstData } = useQuery<ExamType>(
        "exam",
        fetData,
        {
            refetchOnWindowFocus: false,
            retry: 0,
        },
    );

    const { isLoading: jobLoading, data: jobData } = useQuery<ExamType2>(
        "job",
        fetchJobData,
        {
            refetchOnWindowFocus: false,
            retry: 0,
            enabled: !!firstData,
        },
    );

    const { isLoading: userLoading, data: userData } = useQuery<ExamType3>(
        ["user", "1234"],
        (params) => {
            return fetchOneUser(params.queryKey[1]);
        },
        {
            refetchOnWindowFocus: false,
            retry: 0,
            enabled: !!jobData,
        },
    );

    ....

    return (
        <div>
            <Head>
                <title>Create Next App</title>
                <meta
                    name="description"
                    content="Generated by create next app"
                />
                <link rel="icon" href="/favicon.ico" />
            </Head>
            {!firstLoading ? (
                <Exam data={firstData} />
            ) : (
                <Loading seq="first" />
            )}
            <button
                onClick={() => {
                    putEmail.mutate();
                }}>
                email 변경
            </button>
            {!jobLoading ? <Exam2 data={jobData} /> : <Loading seq="job" />}
            {!userLoading ? (
                <>
                    <p>name : {userData?.name}</p>
                    <p>email : {userData?.email}</p>
                </>
            ) : (
                <Loading seq="user" />
            )}
        </div>
    );
};

이 unique key는 동적 라우팅 한후 id를 이용해서 많이 사용되어 질것 같다.

오늘 react-query를 마무리 하고 싶었지만 지금으 새벽 5시 23분 너무 잠이온다....
마지막 남으 options는 다음시간에 정말 마무리 해보도록하자.

참조
https://kyounghwan01.github.io/blog/React/react-query/basic/
https://www.programcreek.com/typescript/?api=react-query.useQueries

profile
안녕하세요 주니어 프론트엔드 개발자 이지훈입니다.

0개의 댓글