반응형
250x250
Notice
Recent Posts
Recent Comments
Link
관리 메뉴

짧은코딩

리덕스 내부 구조 잡기 본문

인프런, 유데미/Redux

리덕스 내부 구조 잡기

5_hyun 2022. 9. 10. 22:46

원본 파일

const { createStore } = require("redux");

const reducer = (prevState, action) => {
  switch (action.type) {
    case "LOG_IN":
      return {
        ...prevState,
        user: action.data,
      };
    case "LOG_OUT":
      return {
        ...prevState,
        user: null,
      };
    case "ADD_POST":
      return {
        ...prevState,
        posts: [...prevState.posts, action.data],
      };
    default:
      return prevState;
  }
};

const initialState = {
  user: {
    isLoggingIn: true,
    data: null,
  },
  posts: [],
  comments: [],
  favorites: [],
  history: [],
  likes: [],
  followers: [],
};


const store = createStore(reducer, initialState);

console.log(store.getState());

const logIn = (data) => {
  // action
  return {
    type: "LOG_IN",
    data,
  };
};

const logOut = () => {
  return {
    type: "LOG_OUT",
  };
};

const addPost = (data) => {
  return {
    type: "ADD_POST",
    data,
  };
};

// 위 부분까지는 미리 만들어 놔야하는 코드
//___________________________________
// 아래 코드는 리액트에서 실행하는 코드, 즉 dispatch 부분은 리액트에서

store.dispatch(
  logIn({
    id: 1,
    name: "zerocho",
    admin: true,
  })
);

store.dispatch(
  addPost({
    userId: 1,
    id: 1,
    content: "안녕하세요, 리덕스",
  })
);

store.dispatch(
  addPost({
    userId: 2,
    id: 2,
    content: "안녕하세요, 리덕스2",
  })
);

console.log(store.getState());

간단한 기능 구현이지만 코드 길이가 너무 길어서 코드를 나눠줘야 한다.

 

reducers를 나누는 방법은 reducers 폴더를 하나 만들어서 reducer 함수를 이 폴더의 파일로 옮긴다.

이렇게 옮길 수 있는 이유는 reducer가 순수 함수이기 때문이다. 순수 함수 매개 변수와 함수 내부에서 선언한 변수를 빼고는 다른 것을 참조하지 않는 것이다. 따라서 자유롭게 옮길 수 있다.

 

initialState 이 안에 user 안에 isLoggingIn, data 같은 값을 넣어줄 수 있다. 하지만 posts안에 comments를 넣어주기엔 comments 값이 커질 수 있기 때문에 넣으면 안된다. 배열을 가진 값들은 웬만하면 따로(가장 상위 레벨에) 두는 것이 좋다. 그래야 나중에 불러오기가 편하다.

최종 폴더 구조

폴더는 이렇게 actions, reducers, index2.js로 나눴다.

1. actions에는 action이 들어가 있으며 post를 담당하는 post.js, user를 담당하는 user.js로 나눴다.

2. reducer에는 reducer 함수를 넣어줬다. 파일 이름이 index.js인 이유는 보통 대표 파일은 index로 짓기 때문이다.

 

=> 이렇게 나눴어도 기능에 따라 더 세분화해서 나눠야한다. 그리고 나누는 기준은 항상 초기값, 데이터를 기준으로 나눠야한다. 잘 나눌 수 있기 위해서는 많은 프로젝트 경험이 중요하다.

actions 나누기

-actions/post.js

const addPost = (data) => {
  return {
    type: "ADD_POST",
    data,
  };
};

module.exports = {
  addPost,
};

 

-actions/user.js

const logIn = (data) => {
  // action
  return {
    type: "LOG_IN",
    data,
  };
};

const logOut = () => {
  return {
    type: "LOG_OUT",
  };
};

module.exports = {
  logIn,
  logOut,
};

reducer 나누기

-reducers/index.js(reducer만 분리 한 파일)

const reducer = (prevState, action) => {
  switch (action.type) {
    case "LOG_IN":
      return {
        ...prevState,
        user: action.data,
      };
    case "LOG_OUT":
      return {
        ...prevState,
        user: null,
      };
    case "ADD_POST":
      return {
        ...prevState,
        posts: [...prevState.posts, action.data],
      };
    default:
      return prevState;
  }
};

module.exports = reducer;

reducer는 함수라서 쪼갤수가 없다. 그렇기에 제공하는 것을 사용해야한다. combineReducer라는 것을 제공한다.

 

각각 userReducer, postReducer로 쪼개고 이 쪼갠것을 combineReducers로 합쳐서 exports 해줄 수 있다.

따라서 결국 파일을 index.js, user.js, post.js로 나눌 수 있다. index.js에서 user와 post에서 넘겨준 reducer를 합쳐준다.

-user.js

const initialState = {
  isLoggingIn: false,
  data: null,
};

const userReducer = (prevState = initialState, action) => {
  switch (action.type) {
    case "LOG_IN":
      return {
        ...prevState,
        data: action.data,
      };
    case "LOG_OUT":
      return {
        ...prevState,
        data: null,
      };

    default:
      return prevState;
  }
};

module.exports = userReducer;

이렇게 따로 나눴으니 initialState인 기본값을 설정해야 한다.

이 reucer는 user 객체만 가리키기 때문에 data로만 표현을 해도 된다.

 

-post.js

const initialState = [];

const postReducer = (prevState = initialState, action) => {
  switch (action.type) {
    case "ADD_POST":
      return [...prevState, action.data];
    default:
      return prevState;
  }
};

module.exports = postReducer;

이렇게 따로 나눴으니 initialState인 기본값을 설정해야 한다.

여기서 prevState로만 해도된다. 왜냐하면 reducer를 나눠줬으니까 posts만 가리키게 되기 때문이다. 그리고 posts만 가리키도록 범위가 좁아져서 객체 형식으로 하지 않아도 된다.

 

-reducers/index.js

const { combineReducers } = require("redux");
const userReducer = require("./user");
const postReducer = require("./post");

module.exports = combineReducers({
  user: userReducer,
  posts: postReducer,
});

이런식으로 구성이 가능하다.

728x90
반응형

'인프런, 유데미 > Redux' 카테고리의 다른 글

immer(코드를 줄일 수 있음)  (0) 2022.11.18
리액트와 리덕스 연결하기, redux devtools  (0) 2022.11.18
redux-thunk  (0) 2022.11.18
리덕스 미들웨어  (0) 2022.09.13
Redux를 사용하는 이유 및 기본  (0) 2022.09.06
Comments