본문 바로가기
  • 삽질하는 자의 블로그
Redux, Redux-toolkit

8. [ Redux-toolkit ] 리덕스에서 fetch 사용하여 DB 의 값 GET 요청하고 STATE 에 넣기

by 이게뭐당가 2022. 12. 20.

Thunk 액션 생성자를 이용한, 비동기 함수의 사용 ( fetch ) 는, 다름이 아니라,

코드의 가독성과 컴포넌트 Fat 을 피하기 위한 한가지 방법일 뿐, 필수가 아니라는 사실을 생각하자.

 

필요에 의해, 함수 내에, fetch 함수를 바로 사용해도, 문제는 없다.

다만, 컴포넌트 Fat 은 보기에 불편하므로, Thunk 액션생성자를 사용하여, 비동기함수를 실행할 것이다.

 

 

1. store 안의 action 을 분리한다.

 

Slice 안에는, State 를 조작하는 기본 Slice.reducerSlice.actions이 export 되고

actions 안에는 비동기 함수, 사이드이펙트 함수 가 정의되어 export 된다.

* Slice (Redux) 안의, 리듀서함수(state, action 담당) 에는, "순수함수" 만이 들어갈 수 있음을 인지하자

 

[Slice]

    import { createSlice } from "@reduxjs/toolkit";

    const initialState = {
      allQuotes: [],
    };

    const quotesSlice = createSlice({
      name: "quotes",
      initialState,
      reducers: {
        addQuotes(state, action) {
          state.allQuotes.push(action.payload.quotes); // quotes 는 id, content, auythor 이 있는 객체
        },
        replaceQuotes(state, action) {
          state.allQuotes = action.payload;
        },
      },
    });

    export const quotesActions = quotesSlice.actions;

    export default quotesSlice.reducer;
[ Actions ]  - 비동기 함수를 위한, Thunk 액션생성자

    import { quotesActions } from "./quotes-slice";
    import { uiActions } from "./ui-slice";

    export const getQuotesData = () => {			// [ 일반함수 ] 정의
      return async (dispatch) => {				// [함수 반환] dispatch 파라미터를 사용한, 
        dispatch(uiActions.fetchLoading(true)); 		// [로딩]시작하면 로딩

        const fetchData = async () => {				// [ 비동기 함수(fetch) 정의]
          const response = await fetch(
            "https://react-router-project-41a4b-default-rtdb.firebaseio.com/Quotes.json"
          );

          const responseData = await response.json();

          const refinedData = [];	      	// 파이어베이스 에서 오는 것 재정리

          for (const key in responseData) {
            refinedData.push({
              id: responseData[key].id,
              content: responseData[key].content,
              author: responseData[key].author,
            });
          }

          return refinedData;
        };

        const allQuotes = await fetchData();		// [ 비동기 함수(fetch) 실행]
        dispatch(uiActions.fetchLoading(false)); 	// [로딩]끝나면 로딩 끝

        dispatch(quotesActions.replaceQuotes(allQuotes));	// [결과값 State 에 입력]
      };
    };

 

2. 원하는 곳에 가서 사용한다.

 

이 함수는 모든 DB 데이터를 가져오는 함수이고,

 all-quotes(모든 데이터) 를 보여주는, 컴포넌트가 있으므로, 그곳에서 사용하도록 하였다.

 

< AllQuotes Component>    
    
    import AllQuotesComponent from "../components/quotes/all-quotes";
    import { useDispatch, useSelector } from "react-redux";
    import { getQuotesData } from "../store/quotes-actions";
    import { useEffect } from "react";

    const AllQuotes = () => {
        const uiState = useSelector((state) => state.uiSlice.getFetchLoading);      // uiState를 가져온다

        const dispatch = useDispatch();

        useEffect(() => {
            dispatch(getQuotesData());	// dispatch 를 통해, 실행한다 **
        }, [dispatch]);

        if (uiState) {
            return <p> loading</p>;     // uiState 가 true 면 Loading 이 나오게한다.
        }				//  [후에, 다른 컴포넌트나, 로딩스피너, CSS 다 적용시켜서도 가능]

        return (
            <div>
                <h1>명언들</h1>
                <main>
                    <AllQuotesComponent />
                </main>
            </div>
        );
    };

    export default AllQuotes;

댓글