react -redux(thunk) case #1

SANGKU OH·2020년 9월 30일
0
post-thumbnail

상태관리를 redux-thunk를 통해 fetch를 받고 store에서 metaData를 관리하도록 변경해 보았다.

💡해당 포스팅에서는 ducks 스타일로 코드를 작성하였습니다.

middleware

1. 미들웨어란?

미들웨어는 액션이 디스패치(dispatch)되어서 리듀서에서 이를 처리하기전에 사전에 지정된 작업들을 설정하는 공간입니다.

💡쉽게 미들웨어는 액션과 리듀서 사이의 중간자라고 이해하도록 해보자!

2. 미들웨어 만들어보기

const loggerMiddleware = store => next => action => {
    /* 미들웨어 내용 */
}

next는 store.dispatch와 비슷한 역할을 합니다.

💡 차이점

  • next(action)을 했을 때에는 바로 리듀서로 넘기거나, 혹은 미들웨어가 더 있다면 다음 미들웨어 처리가 되도록 진행합니다.
  • store.dispatch의 경우에는 처음부터 다시 액션이 디스패치 되는 것 이기 때문에 미들웨어를 다시한번 처리하게 됩니다.

  • 액션의 실행
  • 미들웨어의 실행
  • next를 통한 다음 미들웨어의 실행
  • 리듀서의 실행

그럼 한번 미들웨어를 만들어보자!

미들웨어

const loggerMiddleware = store => next => action => {
    // 현재 스토어 상태값 기록
    console.log('현재 상태', store.getState());
    // 액션 기록
    console.log('액션', action);

    // 액션을 다음 미들웨어, 혹은 리듀서로 넘김
    const result = next(action);

    // 액션 처리 후의 스토어 상태 기록
    console.log('다음 상태', store.getState());
    console.log('\n'); // 기록 구분을 위한 비어있는 줄 프린트

    return result; // 여기서 반환하는 값은 store.dispatch(ACTION_TYPE) 했을때의 결과로 설정됩니다
}

export default loggerMiddleware; // 불러와서 사용 할 수 있도록 내보내줍니다.

3. 미들웨어 적용하기

미들웨어는 store를 생성할 때 설정합니다.
redux 모듈안에 들어있는 applyMiddleware를 사용하여 설정합니다.

import { createStore, applyMiddleware } from 'redux';
import modules from './modules';
import loggerMiddleware from './lib/loggerMiddleware';

// 미들웨어가 여러개인경우에는 파라미터로 여러개를 전달해주면 됩니다. 예: applyMiddleware(a,b,c)
// 미들웨어의 순서는 여기서 전달한 파라미터의 순서대로 지정됩니다.
const store = createStore(modules, applyMiddleware(loggerMiddleware))

export default store;

4. redux-thunk

리덕스를 사용하는 어플리케이션에서 비동기 작업을 처리할때 쓰는 미들웨어!
객체 대신 함수를 생성하는 액션 생성함수를 작성 할 수 있게 해줍니다.
리덕스에서는 기본적으로 액션 객체를 디스패치 합니다.

const actionCreator = (payload) => ({action: 'ACTION', payload});

만약 특정 액션이 몇 초 뒤에 실행되게 하거나, 현재 상태에 따라 아예 액션이 무시되게 하려면, 일반 액션 생성자로는 할수 없습니다. but, redux-thunk는 이를 가능케합니다!

#case 1

const INCREMENT_COUNTER = 'INCREMENT_COUNTER';

// action 함수
function increment() {
  return {
    type: INCREMENT_COUNTER
  };
}

// thunk 함수
function incrementAsync() {
  return dispatch => { // dispatch 를 파라미터로 가지는 함수를 리턴합니다.
    setTimeout(() => {
      // 1 초뒤 dispatch 합니다
      dispatch(increment());
    }, 1000);
  };
}

이렇게 thunk함수를 작성한다면 나중에 store.dispatch(incrementAsync());를 하면 INCREMENT_COUNTER액션이 1초뒤에 디스패치됩니다!

#case 2


// thunk 함수
function incrementIfOdd() {
  return (dispatch, getState) => {
    const { counter } = getState();

    if (counter % 2 === 0) {
      return;
    }

    dispatch(increment());
  };
}

🚨 만약, 리턴하는 함수에서 dispatch, getState를 파라미터로 받게 한다면 스토어의 상태에도 접근이 가능합니다.
따라서, 현재 스토어의 상태 값에 따라 액션이 dispatch될 지, 무시될 지 정해줄 수 있게 됩니다!

🤔 dispatch,getState는 어디서오는 거죠~?

redux-thunk 미들웨어에서, 전달받은 액션이 함수형태일 때,
그 함수에 dispatch와 getState를 넣어서 실행해줍니다.

action

  • GET_DATA type을 정의했다.
  • getData라는 이름으로 action 함수를 정의했다.

thunk

✨오늘의 주인공! Thunk 함수✨

  • thunk함수 내부에서 fetch를 진행하도록 설정했다.
  • fetch를 받은 후 response를 action함수 getData의 인자로 넘겨주었다

reducer

  • reducer를 통해 GET_DATA 액션이 일어날 경우 state 값을 변경한다.

store

  • store부분에서 thunk를 import 한다.
  • store를 생성하는 parameter에 applyMiddleware(thunk) 형태로 thunk를 추가해준다!

    본 프로젝트에는 thunk 외에 saga를 추가로 사용할 예정이다.
    따라서 middlewares라는 변수 내부에 사용할 미들웨어들을 묶음으로 지정하여 binding을 했다.

use

  • 컴포넌트에서 thunk 함수인 fetchingData를 import!

  • useEffect함수를 통해 thunk 함수인 fetchingData를 컴포넌트가 마운트될때 실행되도록 설정했다.

result

  • console.log를 보면 tagReducer의 data부분에 fetch받은 데이터들이 정상적으로 들어와 있다! 🎉
profile
Prof.Google을 통해 필요한 정보를 이 곳에 insert 🐸

0개의 댓글