본문 바로가기
React

2021.08.18 React react-redux, redux-middleware

by 해맑은 코린이 2021. 8. 18.

2021.08.18 React react-redux, redux-middleware_정리노트 

 

오늘은~~~ 리덕스 미들웨어에 대해서 포스티ㅣㅣㅣㅣㅇ~~~~ 흑흑.. 사실 저번 리액트에서 리덕스 연결하기에 대한 포스팅이 개인적으로 마음에 들지 않는다. 개념을 이해하고 썼다기 보다는 개념을 나열한 것뿐.. 그래서 이어서 이 미들웨어에 대한 포스팅을 적는 것에서도 많은 걱정이 들지만, 이 개념들을 나열하면 언젠가 쓰면서 다시 정리할 기회가..? 생기지 않을까 하는 긍정적인 마인드....ㅎ..로 조심스럽게 미들웨어 포스팅 또한 쓰려 한다! 

 

https://korinkorin.tistory.com/75?category=974678 

 

2021.08.16 React-redux

2021.08.16 React-redux_정리노트 드디어 프로젝트에서 실습 코드를 치면서 리덕스에 대해 다뤄보자!!!! 으으 화이텡... 그 전 포스팅 https://korinkorin.tistory.com/74?category=974678 2021.08.10 redux libra..

korinkorin.tistory.com

 

아마 이 게시물은 곧... 비공개로 돌려질 것 같다. 대신에 미들웨어 들어가기전에 매우 복잡하게 들어가지 않더라도 간단하게 주석으로 다시 리덕스의 흐름을 쭈루룩 잡고 들어가볼 생각!

아마 이 포스팅에서 리액트에 리덕스를 연동하는 작업의 전반적인 흐름을 잡고, 미들웨어까지 같이 흐름으로 정리해보자!!!

 


 

자 시작!

 

https://korinkorin.tistory.com/74

 

2021.08.10 redux library-tutorial

2021.08.10 redux library-tutorial_정리노트 오늘은 드디어 리덕스를 들어간다...! 리덕스는 리액트뿐만 아니라, Js App 에서 예측 가능한 상태들을 관리하는 컨테이너 라이브러리! 그러니 리액트에서 사

korinkorin.tistory.com

 

엉망진창인 저 위보다는 조금 더 개념적인 부분에서 튜토리얼은 남겨두었음! 리덕스는 리액트뿐만 아니라 자바스크립트 기반 라이브러리/ 프레임워크에서도 쓸 수 있고, 상태를 효율적으로 관리할 수 있는 라이브러리라고 적었다. 리액트처럼 복잡한 상태 관리가 이루어지는 SPA 에서 특히 유용하게 사용된다. 

 

 

이렇게 혼자서 개념을 정리하다보니.. 그러면 우리가 저번에 배웠던 Context API 랑 다른게 뭔가 싶어서 혼자 또 구글링구글링..

 

단순히 책에서는 Context API 를 가지고  리덕스를 만들었다고만 해서.. 홀홀 

둘은 전역 상태 관리를 위한 도구라는 공통점을 가지고 있지만, 차이점을 통해서 리덕스의 장점을 간단하게 나열하면

 

Context API 는 리액트에서만 사용 가능하고 여러 저장소 생성이 가능. 

 

Redux 는 전역 상태 관리외에 다양한 기능을 제공. Context API 는 부가적인 기능을 제공하지 않아 다른 라이브러리의 도움을 필요.

 

결론 : redux 에서는 다양한 추가 라이브러리를 통해 우리가 좀 더 상태 관리를 수월하게 하고 긴밀하고 정확한 코딩을 할 수 있도록 돕는다. 

 

https://velog.io/@cada/React-Redux-vs-Context-API

 

React Redux vs Context API

본 글은 아래를 참고하여 작성되었습니다. 더 자세한 사항을 알고싶으신 분은 아래 링크를 참고해주세요.Academind - Redux vs React\`s Context APIDan Abrarnov - You Might Not Need ReduxRedux란?Contex

velog.io

 

이분의 블로그를 보고 참고해서 나도 정리했다! 굿굿..! 그러니 작은 프로젝트에 많은 기능이 필요 없는 간단한 프로젝트에서는 굳이 리덕스가 필요없을 것이다. 하지만 프로젝트의 복잡도가 높아지면 리덕스를 사용하여 전역 상태 관리를 훨씬 체계적이고 수월하게 할 수 있다는 말이 된다!

 

 

 

리덕스에서는 동기적인 흐름을 통해 동작하는데, 액션 객체가 생성되고, 디스패치가 액션 발생을 스토어에게 알리면, 리듀서는 정해진 로직에 의해 액션을 처리한 후 새로운 상태값을 반환하는 과정. 이 디스패치된 액션을 스토어에게 전달하기 전에 비동기적으로 처리하고 싶은 작업이 있을 수 있다. 

예를 들어서 외부 데이터의 요청이 시작되었을 때 띄워주는 로딩중 화면, 외부 데이터를 요청하여 서버에서 받아 온 응답에 대한 상태를 관리하고, 요청이 실패하면 에러에 대한 상태를 관리하는 작업등!! 

리액트 프로젝트에서 리덕스를 사용할 때 이러한 비동기 작업을 관리해야 한다면, 미들웨어를 사용하여 매우 효율적이고 편하게 상태 관리를 할 수 있다. 

 

책에서 말한대로 미들웨어의 개념을 이해하고, 미들웨어를 사용하여 비동기 작업을 어떻게 처리하는지 같이 정리하며 포스팅 해보자!

 

프로젝트 생성!

 

$ yarn create react-app learn-redux-middleware

// 라이브러리 설치
$ yarn add redux react-redux redux-actions

 

src/modules/counter.js ( 새로 생성 )

 

counter 리덕스 모듈을 작성. 각각 주석으로 흐름 정리.

 

 

src/modules/index.js ( 새로 생성 )

리듀서를 모아주는 루트리듀서를 작성하고,

 

src/index.js

 

원래 있던 index.js 니까 헷갈리지 말자!! 스토어 생성후, 리액트와 연동하기 위해 Provider 컴포넌트로 App 을 감싸주었다.

 

 

이제는 프레젠테이셔널 컴포넌트와 컨테이너  컴포넌트를 만들 차례!

 

그 전 게시물이... 반복하지만 넘 더러워서 여기에 다시 간단하게 정리!

 

 

 

프레젠테이셔널 컴포넌트

상태관리가 이루어지지 않고 , 그저 props 를 받아와서 화면에 UI 를 보여주기만 하는 컴포넌트를 말함.

 

컨테이너 컴포넌트

리덕스와 연동되어 있는 컴포넌트.

리덕스로부터 상태를 받아 오기도 하고 리덕스 스토어에 액션을 디스패치하기도 한다.

 

 

이러한 패턴은 리덕스를 사용하는데 필수 사항은 아님. 다만 이 패턴을 샤용하면 코드의 재사용성도 높아지고, 관심사의 분리가 이루어져 UI 를 작성할 때 좀 더 집중해서 사용할 수 있다!

 

쨋든 이 패턴대로,

 

 

src/components/Counter.js ( 새로 생성 )



 

UI 를 보여주는 프레젠테이셔널 컴포넌트 생성.

 

 

src/container/CounterContainer.js ( 새로 생성 )

import React from "react";
import { connect } from "react-redux";
import { increase, decrease } from "../modules/counter";
import Counter from "../components/Counter";

const CounterContainer = ({ number, increase, decrease }) => {
  return (
    <Counter number={number} onIncrease={increase} onDecrease={decrease} />
  );
};

// connect 함수 : 첫번째 인자에는 mapStateToProps. 즉 리덕스 스토어 안에 있는 state ( 상태 ) 를 컴포넌트의 props 로 넘겨주기 위해 사용하는 함수.
// 두번째 파라미터로는 mapDispatchToProps. 즉 액션 생성함수를 넣는 곳인데, 객체 형태로 액션 생성함수 자체를 넣어주게 되면, connnect 함수가 bindActionCreators 라는 유틸함수가 자동으로 인식되어 작업을 해주는데, 얘는 액션을 디스패치할 때 쓰는 유틸 함수.

export default connect(
  (state) => ({
    number: state.counter,
  }),
  {
    increase,
    decrease,
  }
)(CounterContainer);

 

컨테이너 컴포넌트도 작성해주었따.

주석이 기니까 블럭으로 작성. 정말정말 압축해서 한번에 정리함...! 리덕스를 리액트에 연동시키는 작업이다..!!

즉, 리덕스로부터 상태를 받아 오기도 하고 리덕스 스토어에 액션을 디스패치하기도 한다. 이를 connect 라는 리액트 리덕스에 있는 함수를 사용해서 적어준 것!!!! 

 

 

으아.. 정말 함ㅁㅁㅁ축해서 작성해주었따!! 

 

이제 마지막으로 컨테이너 컴포넌트를 App 에서 렌더링하여 잘 작동하는지 확인해보자!!

 

src/App

 

실행 화면

 

redux-Devtools 를 설치해서 보고 싶다면 ? 

 

https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd?hl=ko 

 

Redux DevTools

Redux DevTools for debugging application's state changes.

chrome.google.com

 

설치하고,

 

$ yarn add redux-devtools-extension

 

리액트 상에서도 확장프로그램 설치 후, 

 

 

src/index

이렇게 적용시켜주면,

 

 

개발자 도구 Redux 탭에서 지금 우리의 스토어 state 인 내부 상태가 잘 뜬다.  어떤 액션이 발생하는지도 정의된 이름에 맞게 잘 뜨니까 훨씬 수월한듯!!!!!

 


ㅎ..... 이제 미들웨어로 들어갈 차례

간단하게 위의 내용을 다시 요약!

 

미들웨어

리덕스 미들웨어는 액션을 디스패치했을 때 리듀서에서 이를 처리하기에 앞서 사전에 지정된 작업들을 실행. 미들웨어는 액션과 리듀서 사이의 중간자라고 볼 수 있음. 작업은 여러 가지가 있는데 , 전달받은 액션을 단순히 콘솔에 기록하거나, 전달받은 액션 정보를 기반으로 액션을 아예 취소해버리거나 다른 종류의 액션을 추가로 디스패치할 수도 있음.

 

 

아까 redux-logger 라는 만들어진 미들웨어를 사용하기 전에..! 어떻게 작동하는지 이해하기 위해 직접 만들어보자! 이렇게 제대로 이해해놓으면 원하는 미들웨어가 없을 때는 상황에 따라 직접 만들거나 기존 미들웨어를 커스텀하는 것도 가능 하니 ㅎㅎ 물론 멋찐 개발자분들이 만들어 놓지 않는 경우는 거의 없겠지만서도 ㅎㅁㅎ

 

 

그러니 액션이 디스패치될 때마다 액션의 정보와 액션이 디스패치되기 전후의 상태를 콘솔에 보여주는 로깅 미들웨어를 직접 만들어보자!

 

 

src/lib/loggerMiddleware.js ( 새로 생성 ) 

 

음뇽뇽.... 엄청 헷갈.....린다 리덕스 튜토리얼에서 각각의 용어 정리를 다시 보고 나서야 조금 정리됨ㅋㅋㅋㅋㅋ 액션이 .. 디스패치 되면 얘는 액션 생성 함수에서 생성한 액션 객체를 받아서 액션을 발생시키고, 스토어는 리듀서 안에 있는 함수를 실행시켜서 변화를 일으키고 그 새로운 상태를 스토어에 현재 상태를 나타내는 곳에 담는....그런 과정..... 다시 혼자 중얼중얼.... 정리정리 

 

쨋든 미들웨어는 디스패치가 되고!!! 리듀서가 이를 실행하기에 중간자 역할이기 때문에 스토어의 인스턴스와, action, next 라는 미들웨어만의 store.dispatch 와 유사한 역할을 하는 총 3개의 파라미터를 받는다!!!

 

 

이 미들웨어는 총

 

이전 상태

액션 정보

새로워진 상태

 

 

3가지의 정보를 순차적으로 보여주게 할 것.

 

const loggerMiddleware = store => next => action => {
    console.group(action && action.type); // group 시작
    console.log('이전 상태',store.getState());
    console.log('액션', action);
    next(action); // 다음 미들웨어에 전달. 다음 미들웨어가 없다면 리듀서에게 액션을 넘김.
    console.log('다음 상태', store.getState()); // group 끝.
    console.groupEnd();
 
};


export default loggerMiddleware;

 

console.group 은 단순히 콘솔에 띄울 때 그룹으로 더 잘 보이기 위해서 해준 것!

 

출처 - MDN https://developer.mozilla.org/ko/docs/Web/API/Console/group

 

 

이렇게 전달해주고, 얘를 어디다가 적용하냐면 스토어를 생성하는 과정에서 적용하면 됨!

 

 

src/index

 

import React from "react";
import ReactDOM from "react-dom";
//  compose applyMiddleware import
import { createStore, compose, applyMiddleware } from "redux";

import { Provider } from "react-redux";
import "./index.css";
import App from "./App";

import rootReducer from "./modules";

import loggerMiddleware from "./lib/loggerMiddleware";

// extension 함수 따로 생성 
const composeEnhancer = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
// store 생성, extension 함수에 applyMiddleware 함수로 감쌈.
const store = createStore(
  rootReducer,
  composeEnhancer(applyMiddleware(loggerMiddleware))
);


ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById("root")
);
);

 

갑자기 복잡해지는데, 아까 내가 reduxDevTools 를 사용해서 createStore 에서는 여러개 파라미터를 받지 못하는 오류를 뱉어 내기 때문에 아까 작성했던 extension 적용을 함수로 따로 빼서 applyMiddleware 에 다가 함수로 감싸주어서 그럼 ㅇㅇ 

 

만약 개발자 도구를 사용하지 않았다면, rootReducer 뒷 부분에 applyMiddleware(loggerMiddleware) 만 적어주면 된다!

compose 도 불러오지 않아도 됨!

 

 

실행 화면

 

 

쟌쟌쟌쟌

 

이렇게 그룹으로 깔끔하게 콘솔에 찍혀서 나온다. 이전 counter 의 상태와 액션이 뭐가 발생했는지 가르쳐주고, 새로워진 상태를 잘 반환한다!

 


이렇게 허접하게 내가 만든 미들웨어말고 이제 잘 만들어진 redux-logger 미들웨어를 써보장

 

$ yarn add redux-logger

 

 

src/index

 

 

내가 만든 미들웨어 지우고 그냥 createLogger 를 불러와서 담아주고 applyMiddleware 에 넣어주기만 하면 ...?

 

 

 

 

^^ 훨씬 간단하고 액션 디스패치 시간도 나옴 캬캬 역시 불러와서 쓰는게 최고균

 

 


 

간단한 로거 미들웨어를 써봤으니 비동기 작업을 처리하는 미들웨어도 써볼까!

 

redux-thunk 

비동기 작업을 처리할 때 가장 많이 사용하는 미들웨어. 객체가 아닌 함수 형태의 액션을 디스패치할 수 있게 해줌.

리덕스 창시자가 만든 미들웨어..! 리덕스 공식 메뉴얼에서도 이 미들웨어 사용법 예시가 있다 ㅎㅁㅎ!!!

 

redux-saga

그 다음으로 가장 많이 사용되는 비동기 작업 관련 미들웨어 라이브러리. 특정 액션이 디스패치되었을 때, 정해진 로직에 따라 다른 액션을 디스패치시키는 규칙을 작성하여 비동기 작업을 처리할 수 있게함. 보통 redux-thunk 로 처리하기 조금 더 까다로운 상태에서 많이 쓴다.

 

기존 요청을 취소 처리해야 할 때 (불필요한 중복 요청 방지)

 

특정 액션이 발생했을 때 다른 액션을 발생시키거나 , API 요청 등 리덕스와 관계없는 코드를 실행할 때 

 

웹소켓을 사용할 때

 

API 요청 실패 시 재요청 해야 할 때

 

 

 

 

오늘은 여기서 redux-thunk 를 흐름에 따라 써보기!

 

여기서!!!!  하나 짚고 넘어갈 개념.

 

 

 

Thunk

특정 작업을 나중에 할 수 있도록 미루기 위해서 함수 형태로 감싼 것을 의미.

 

이렇게 해당 함수를 호출해서 바로 호출하는 것이 아닌,

 

 

 

연산을 미루고 fn 이 실행되는 시점에 연산을 하도록 만드는 것을 의미한다.

 

 

const sampleThunk = () => (dispatch, getState )=>{
	// 현재 상태를 참조할 수 있고,
    // 새 액션을 디스패치할 수 있음.
}

요곳은 redux-thunk 에서 쓰는 코드 예시!

 

요걸 써서 코드에 적용 시켜보자.

 

 

$ yarn add redux-thunk

 

src/index

 

이도 역시 스토어를 만들 때 적용해준다!

 

또 redux-thunk 는 아까 액션 객체를 반환하는게 아니라 함수를 반환한다고 했음..!

 

 

이렇게! 액션 생성 함수로 객체를 떤지면 그걸 함수로 반환하도록 increaseAsync, decreaseAsync 함수를 만들었다. 

 

 

모듈을 고쳐줬으니까, 모듈 props 를 가지고 있는 컨테이너로 가서 생성 함수 부분도 바꿔줍씨단.

 

 

이렇게! 

 

 

실행 화면

 

1초 뒤에 카운트가 잘 되면 성공! 또 콘솔을 보면 맨 처음 디스패치 되는 액션은 함수 형태, 그 뒤는 객체 형태로 찍히고 있는 것을 확인할 수 있다. 

 

 


 

그렇다면, API 데이터 요청을 비동기 작업 처리를 해야할 때는 ?

 

http://jsonplaceholder.typicode.com/

 

JSONPlaceholder - Free Fake REST API

{JSON} Placeholder Free fake API for testing and prototyping. Powered by JSON Server + LowDB As of Dec 2020, serving ~1.8 billion requests each month.

jsonplaceholder.typicode.com

 

요 fake API 로 연습하기 ㄱ!

 

$ yarn add axios

 

API 를 호출하기 위해서 axios 깔아주기.

 

그리고 API 호출을 모두 함수화 해줄 건데, 각 API 를 호출하는 함수를 따로 작성하면, 나중에 사용할 때 가독성도 좋고 유지보수도 쉬워진다!

 

src/lib/api.js ( 새로 생성 )

 

이렇게 작성해주었으면 리듀서 만들어야지!! 가자! 

 

 

modules/sample.js ( 새로 생성 )

 

import { handleActions } from "redux-actions";
// api 에 있는 export 모두 import
import * as api from '../lib/api'


// 하나의 요청당 세 가지의 액션 타입 선언


const GET_POST = 'sample/GET_POST';
const GET_POST_SUCCESS = 'sample/GET_POST_SUCCESS';
const GET_POST_FAILURE= 'sample/GET_POST_FAILURE';


const GET_USERS = 'sample/GET_USERS';
const GET_USERS_SUCCESS = 'sample/GET_USERS_SUCCESS';
const GET_USERS_FAILURE= 'sample/GET_USERS_FAILURE';


// thunk 함수 생성 .

export const getPost = id => async dispatch =>{
    //  요청을 시작했을 때 
    dispatch({type:GET_POST});
    try{
        const response = await api.getPost(id);
        //  성공했을 때
        dispatch(
            {
                type:GET_POST_SUCCESS,
                payload:response.data
            }
        )
    }catch(e){
        // 실해팼을 때
        dispatch({
            type:GET_POST_FAILURE,
            payload:e,
            error: true
        });
        // 컴포넌트단에서 나중에 에러를 조회할 수 있게 해줌.
        throw e ;
    }
};


export const getUsers = () => async dispatch =>{
    //  요청을 시작했을 때 
    dispatch({type:GET_USERS});
    try{
        const response = await api.getUsers();
        //  성공했을 때
        dispatch(
            {
                type:GET_USERS_SUCCESS,
                payload:response.data
            }
        )
    }catch(e){
        // 실해팼을 때
        dispatch({
            type:GET_USERS_FAILURE,
            payload:e,
            error: true
        });
        // 컴포넌트단에서 나중에 에러를 조회할 수 있게 해줌.
        throw e ;
    }
};

// 초기 상태 지정
const initialState = {
    loading:{
        //  요청 중 로딩 상태는 loading 객체에서 관리
        GET_POST : false,
        GET_USERS: false
    },
    post:null,
    users:null
};


// 리듀서 함수
const sample = handleActions(
    {
        [GET_POST]: state =>({
            ...state,
            loading:{
                ...state.loading,
                GET_POST:true // 요청 시작

            }
        }),
        [GET_POST_SUCCESS]:(state,action) =>({
            ...state,
            loading:{
                ...state.loading,
                GET_POST:false // 요청 완료

            },
            post:action.payload
        }),
        [GET_POST_FAILURE]:(state,action) =>({
            ...state,
            loading:{
                ...state.loading,
                GET_POST:false // 요청 완료

            }
        }),
        [GET_USERS]:state =>({
            ...state,
            loading:{
                ...state.loading,
                GET_USERS:true // 요청 시작

            },
        }),

        [GET_USERS_SUCCESS]:(state,action) =>({
            ...state,
            loading:{
                ...state.loading,
                GET_USERS:false // 요청 완료

            },
            users:action.payload
        }),
        [GET_USERS_FAILURE]: (state,action) =>({
            ...state,
            loading:{
                ...state.loading,
                GET_USERS:true // 요청 완료

            },
        })
    },
    initialState
);

export default sample;

아구 .. 길다 불변성을 유지하면서 해줘야하기 때문에 반복되는 코드들도 많긴..하지만 흐름을 위해서는 이렇게 하나하나 길게 작성해주는게 최선인듯 ㅠ0ㅠ 

 

 

src/modules/index

리듀서를 하나 더 생성해주었으니, 루트 리듀서 또한 추가해주기.

 

 

 

그러고 나서 이제 UI 를 띄워주어야 하는 프레젠테이셔널 컴포넌트를 만들어야 하는데, 데이터 형태를 보고 우리가 띄워줄 데이터들만 뽑아서 보여줄 예정

 

https://jsonplaceholder.typicode.com/posts

 

https://jsonplaceholder.typicode.com/users

 

 

여기서 우리가 원하는 정보만 뽑아서 보여주기.

 

 

 

src/components/Sample.js ( 새로 생성 )

 

import React from "react";

const Sample = ({ loadingPost, loadingUsers, post, users }) => {
  return (
    <div>
      <section>
        <h1>post</h1>
        {/* 해당값이 true 일 때 로딩중 텍스트 띄우기 */}
        {loadingPost && "로딩중..."}
        {/* 로딩 상태는 alse 값 , post 의 값은 true 일 때 UI >> post 객체에 대한 유효성 검사를 해야 자바스크립트 오류를 안띄움.*/}
        {!loadingPost && post && (
          <div>
            <h3>{post.title}</h3>
            <h3>{post.body}</h3>
          </div>
        )}
      </section>
      <hr />
      <section>
        <h1>users</h1>
        {/* 로딩 상태값이 true일때 로딩중 텍스트 띄우기 */}
        {loadingUsers && "로딩중..."}
        {/* 로딩 상태 값이 false, users 값은 true 일 때 UI >> 유효성 검사>> 여기도 마찬가지로 users 배열이 들어와서 map 으로 돌린 후,users 객체가 있을 때만 해당 UI 를 띄워줌. */}
        {!loadingUsers && users && (
          <ul>
            {users.map((user) => (
              <li key={user.id}>
                {user.username}({user.email})
              </li>
            ))}
          </ul>
        )}
      </section>
    </div>
  );
};

export default Sample;

각각 데이터 유효성을 검사하는 이유는 우리가 조건으로 각 데이터가 들어왔을 때의 UI 를 렌더링 해주기 때문에, 만약 빈 배열이나, 객체가 들어오게 되면 자바스크립트 오류를 띄우기 때문. 

 

 

이제 마지막으로 리액트랑 리덕스 연동하는 컨테이너 컴포넌트를 만들어줍씨단!!

 

src/container/SampleContainer.js ( 새로 생성 )

 

import React from "react";
import { connect } from "react-redux";
import Sample from "../components/Sample";
import { getPost, getUsers } from "../modules/sample";

// 컴포넌트 UI 가 화면에 보이는 시점에서 API 요청을 하기 위해서 useEffect 사용.
const { useEffect } = React;

const SampleContainer = ({
  getPost,
  getUsers,
  post,
  users,
  loadingPost,
  loadingUsers,
}) => {
  useEffect(() => {
    getPost(1);
    getUsers(1);
  }, [getPost, getUsers]);
  return (
    <Sample
      post={post}
      users={users}
      loadingPost={loadingPost}
      loadingUsers={loadingUsers}
    />
  );
};

export default connect(
  // 리덕스 스토어 상태를 컴포넌트의 props 로 넘겨주는 부분.
  ({ sample }) => ({
    post: sample.post,
    users: sample.users,
    loadingPost: sample.loading.GET_POST,
    loadingUsers: sample.loading.GET_USERS,
  }),
  // 액션 생성 함수를 컴포넌트의 props로 넘겨줌.
  {
    getPost,
    getUsers,
  }
)(SampleContainer);

 

후... 이제 마지막이다 App 에서 카운터 컨테이너 대신에 샘플컨테이너로 교체해주면, 

 

 

src/App

 

 

실행 화면

 

 

 

이렇게 ! 하나의 포스트와 10개의 유저가 잘 뜨고 redux-logger 미들웨어가 콘솔에 잘찍히면 성공!

 

 

 


음...이번에는 정리한다고 책의 내용을 그냥 많이 생략했... 크크 ㅠ 모르는 부분은 역시 아직은 완벽히 이해할 수 없겠지..!

리덕스의 흐름을 잘 이해하고 비동기 작업을 미들웨어로 처리하는 작업은....결국 우리가 더 편하기 위해서 작업하는거니까 불편하다면 굳이 사용하지 않아도 되는 방법.....!!!!! 조금 내공이 쌓이면 역시 이또한 언젠가 할 수 있으리라 믿으며..! 오늘의 포스팅 끝끝

 

'React' 카테고리의 다른 글

2021.08.21 React 서버 사이드 렌더링  (0) 2021.08.21
2021.08.20 React 코드 스플리팅  (0) 2021.08.20
2021.08.16 React-redux  (2) 2021.08.16
2021.08.10 redux library-tutorial  (0) 2021.08.10
2021.08.08 React Context API  (2) 2021.08.08

댓글