과제 리뷰1

김영준·2020년 10월 4일
0

과제

목록 보기
2/3
post-thumbnail

과제를 수행하면서 작성한 코드에 대한 내 설명을 작성해 본다.

내가 쓴 코드를 리뷰 하는것이기 때문에, 남이 봤을때는 순서와 정리가 매끄럽지 못할 수 있다ㅠㅠ

리뷰 순서

  1. src/index.js
  2. src/App.js
  3. src/View/Main/MainContainer.js
  4. src/hocs/withView.js
  5. src/store/view.js & src/store/reducers.js & src/store/createStore.js
  6. src/View/Main/MainView.js
  7. src/components/Calender/Calender.js
  8. src/components/HourSelector/HourSelector.js

다음과 같은 순서로 코드를 리뷰하겠다.


  1. src/index.js
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import store from "./store/createStore";

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

<App/>props로 createStore 에서 생성된 store 를 넣어준다.
어떻게 만들어졌는지는 5번에서 추가설명이 될것이다.


  1. src/App.js
import React from "react";
import "./app.scss";
import { Provider } from "react-redux";
import Main from "./View/Main/index";
const App = ({ store }) => {
  return (
    <Provider store={store}>
      {/* Provider 를 이용해 store를 사용할 수 있게 한다. */}
      <Main />
    </Provider>
  );
};

export default App;

App 함수에 props로 들어온 store 를 선언하고 <Provider>App.js 에서 렌더될 Route 를 추가해준다.


  1. src/View/Main/MainContainer.js
import withView from "../../hocs/withView";
import { compose } from "recompose";
import MainView from "./MainView";

// compose 를 이용하여 MainView 에 withView 를 넘겨준다.

const wrappedComponent = compose(withView([{ key: "date" }]))(MainView);

export default wrappedComponent;

recompose 라는 library 가 사용되었다.

recompose 는 hOC(higher Order Component) 를 더 유용하게 사용할 수 있게 만들어진 라이브러리 이다.

위 코드에서 살펴보면 withview 에서 return 한 값을 mainView에 넘겨주겠다는 의미이다.

사용방법리뷰

이제 withView 에서 어떤 내용을 MainView에 넘겨주는지 살펴보자.


  1. src/hocs/withView.js
import React from "react";
import { connect } from "react-redux";
import { receiveView } from "../store/view";

export default (option = []) => (ComposedComponent) => {
  // * 1. 배열이 있다면 해당 배열이 들어오고, 없다면 빈 배열 정의.
  // * 2. ComposedComponent 는 MainView가 될것임.

  class withView extends React.Component {
    render() {
      // * 7. props로 받아온 것(state, dispatch)들을 ComposedComponent 로 넣어준 다음 다시 return 함.
      return <ComposedComponent {...this.props} />;
    }
  }
  const mapStateToProps = (state) => {
    // * 3. store에 있는 state
    // * 4. option 으로 들어온 key 를 이용해 store의 state에 있는 값에 접근함.
    const result = {};
    option.forEach((item) => {
      result[item.key] = state.view[item.key];
    });
    return result;
  };

  const mapDispatchToProps = (dispatch) => ({
    // * 5. 액션함수를 가져옴.
    viewAction: {
      receiveView: (key, state) => dispatch(receiveView(key, state)),
      // dispatch 실행되면 해당 reducer 함수 실행
    },
  });
  // * 6. state 와 dispatch 를 props로 withView 로 넘겨준다.
  return connect(mapStateToProps, mapDispatchToProps)(withView);
};
  • 제일 처음 봐야할 1번,2번 부터 보자.
export default (option = []) => (ComposedComponent) => {};

이부분을 보면 option = []은 옵션이 들어온다. 옵션이 없다면 기본값으로 빈 배열을 가지게 할것이다.

MainContainer 에서 withView([{key: 'date' }])option이 쓰인다.

그리고 composedComponentMainContainer 에서
compose(withView([{key: 'date'}]))(MainView) 맨마지막에 MainView가 된다.

  • 3번, 4번, 5번

3번

redux state(store) 에 있는 값을 props 로 준다는 의미인 함수 mapStateToProps 에서 사용된 코드를 보면

const result = {};
option.forEach((item) => {
  result[item.key] = state.view[item.key];
});
return result;
  1. option 으로 들어온 배열 (즉, key: 'date')forEach 각각의 배열에 어떤 처리를 할것인가 보면,
  2. result 라는 객체에 key : value 형태로 만들겠다는 것이다.
  3. key 로는 option으로 들어온 key (즉, date) 는 redux storeitem.key (즉, date)로 선언하겠다.
  4. result에 저장된 내용을 return 함.

4번,5번

dispatch를 props 로 주는 함수를 보면

const mapDispatchToProps = (dispatch) => ({
    viewAction: {
      receiveView: (key, state) => dispatch(receiveView(key, state)),
      // dispatch 실행되면 해당 reducer 함수 실행
    },
  });
  return connect(mapStateToProps, mapDispatchToProps)(withView);
};

viewAction 이라는 key 로 receiveView 에 (key, state) 를 인자로 넣어주게 되면 receiveView (액션함수)가 실행된다.

액션함수가 실행되면 reducer 가 실행되어 역할수행.

  • 6번
    그리고 connect에서 withView 에 값을 넘겨준다.

  • 7번

    withView class 에서 props 로 받아온 것들을 ComposeComponent 에 넣어준다.

class withView extends React.Component {
  render() {
    // * 7. props로 받아온 것(state, dispatch)들을 ComposedComponent 로 넣어준 다음 다시 return 함.
    return <ComposedComponent {...this.props} />;
  }
}

이렇게 withView (hOC)를 이용해서 값을 넘겨준다.


  1. src/store/view.js & src/store/reducers.js & src/store/createStore.js
  • 5-1 src/store/view.js
export const RECEIVE_VIEW = "RECEIVEW_VIEW";

export const receiveView = (key, state = null) => {
  return {
    key,
    type: RECEIVE_VIEW,
    payload: state,
  };
};

const initialState = {};
export default function viewReducer(state = initialState, action) {
  if (action.type === RECEIVE_VIEW) {
    return Object.assign({}, state, { [action.key]: action.payload });
  } else {
    return state;
  }
}

액션 선언과 액션함수, 리듀서함수를 같은 파일에 작성했다.

액션 함수 receiveViewkeystate 가 들어간다. (state가 없을 경우는 null)

액션함수가 실행되면 viewReducer 가 실행되는데, store 에 key 와 action의 payload 즉 (위에서 설정한 state)가 store에 들어간다.

  • 5-2 src/store/reducer.js
import { combineReducers } from "redux";
import viewReducer from "./view";

export default combineReducers({
  view: viewReducer,
});

reducer 는 하나의 함수로만 존재해야 하기 때문에 여러개의 reducer 함수를 하나로 모아놓은 combineReducer 가 필요하다. combineReducer에 view 에서 만든 viewReducer 를 추가한다.

  • 5-3 src/store/createStore.js
import { createStore } from "redux";
import reducers from "./reducers";
import { composeWithDevTools } from "redux-devtools-extension";
const store = createStore(reducers, composeWithDevTools());

export default store;

이제 store 를 만들어야 한다.

createStore 로 만들고, 안에는 위 파일 (store/reducer.js) 에서 만든 combineReducer 가 들어간다. 그리고 chrome devtool extension (추가설치한 library) 를 넣어줘서 확인할 수 있게 한다.

여기서 만들어진 createStore를 src/index.js 에서 import 한다.


이 이후는 MainView 에 대한 내용이므로 다음포스트에서 진행.

profile
프론트엔드 개발자 김영준 입니다. 디테일함을 키우고 있습니다

0개의 댓글