-
Notifications
You must be signed in to change notification settings - Fork 7
[피어세션 준비] 21.11.04
- 테트리스 회전 알고리즘 구현 (월요일 밤샘)
- SRS(Super Rotation System)
- 블록이 떨어질 때 Freeze 되기까지 판정 (화요일 밤샘)
- 블록이 바닥인지 검사하고 0.5초의 딜레이 동안 움직이지 않으면 Freeze 되게 구현
- 게임 오버 판정 (수요일 밤샘)
- Board 배열에 높이가 4인 부분부터 블록을 생성하고, 블록이 높이가 0 ~ 3인 위치에 쌓이면 게임 오버
- 블록을 생성할 때, 이미 생성된 위치에 블록이 존재한다면 게임 오버
- Oauth 제공 플랫폼간 인증 방식의 차이 존재
- 현재는 하드코딩으로 대응하고 있습니다.
- Higher-Order Components 도입을 통해 해결하려고 합니다.
- 상태관리 라이브러리에 대한 전반적인 경험 부족
- Redux 및 Redux Toolkit 라이브러리에 대한 이해
- 리액트 렌더링 최적화에 대한 이해도 부족
- Typescript....
- any....
- Redux Toolkit
4 개의 함수와 5개의 메서드로 이루어진 간단한 상태관리 라이브러리입니다.
- createStore
- getState()
- dispatch(action)
- subscribe(listener)
- replaceReducer(nextReducer)
- compbineReducers
- appplyMiddleware
- bindActionCreators
- compose
주요 개념은 다음과 같습니다.
하나의 Store 객체에 상태를 저장하고 있고, 이를 수정하기 위해서는 항상 reducer를 통해서만 수정이 가능합니다. 이때 reducer에게 어떤 방식으로 업데이트 할 것인지 명시하는 방법으로 action 객체를 전달하는데, 이를 전달하는 과정을 dispatch라고 합니다.
action
{
'type' : 'ADD_MENU',
'payload': {}
}
reducer
reducerExample (state = {}, action) {
switch(action.type) {
case 'A':
return {...state};
case 'B':
return {...state};
default
return state;
}
}
// switch-case, if/else , object 키 값 기준으로 매칭 등의 방법이 있을 수 있습니다.
// redux toolkit 에서는 마지막 방법을 사용하고 있습니다.
-
createStore(reducer, initalState, enhancer) - store 객체를 반환합니다.
initialState 를 사용할 수도 있지만, 각 reducer의 state parameter에 대해 ES6 의 default parameter 문법을 활용해야 여러개의 reducer를 활용할 경우 더 적합한 방법입니다.
- getState() : 현재 상태 트리 반환
- dispatch(action) : 상태 변경을 일으키는 유일한 방법으로 action을 보냅니다.
- subscribe(listener) : 상태 변경에 대한 리스너를 추가합니다.
- replaceReducer(nextReducer) : store에 등록된 reducer를 새로운 reducer로 교체합니다. code splitting의 상황에서 사용됩니다.
-
combineReducers({reducer1, reducer2, ...}) - helper function입니다.
객체 안에 여러개의 reducer를 담아서 인자로 전달하면 그 reducer들을 모두 실행해서 새로운 객체를 만드는 새로운 reducer를 반환합니다.
-
compose(...fns) - helper function입니다.
익숙한 그 compose 맞습니다. 대부분 함수형 프로그래밍 라이브러리에서 제공하는 함수 합성 유틸리티입니다. 오른쪽에서부터 왼쪽으로 각 함수의 반환값을 인자로 받는 하나의 함수로 조합합니다.
-
bindActionCreators({actionCreator1, actionCreator2, ...}, dispatch) - helper function입니다.
action 객체를 생성해서 store.dispatch()의 인자로 전달하는 기존의 과정을 한단계로 합치기 위한 함수입니다. actionCreator - 인자를 전달받아 원하는 형태의 action 객체를 생성하는 함수
-
applyMiddleware
enhancer - 리액트에서 고차 컴포넌트와 같은 개념 저장소 생성자를 전달받아 기능이 추가된 새로운 저장소 생산자를 반환합니다.
applyMiddleware는 enhancer를 반환합니다. 주어진 middleware가 적용되어있습니다.
각 미들웨어는 (store) => (next) => (action) 형태로 선언됩니다.
react에서 사용하기 위해서는 내부적으로 contextAPI를 사용해야합니다. redux store를 하나의 context로 제공하고, 이를 활용하는 render 트리 내부의 다양한 컴포넌트들이 store의 상태 변화를 구독해야합니다. 이러한 내부적인 연결API를 제공하는 라이브러리가 react-redux이고 크게 두가지 방법이 존재합니다. Hook 기반의 api와 HoC로 접근하는 connectAPI가 있고, 이 둘은 어느 하나가 절대적인 우위를 가지지 않고 서로 장단점이 분명합니다.
- hookAPI
useSelector(state => state)로 store의 상태를 가져올 수 있습니다. useDispatch() 로 dispatch 함수를 직접 사용할 수 있습니다.
/* use-actions */
import { bindActionCreators } from "redux";
import { useDispatch } from "react-redux";
import { useMemo } from "react";
export function useActions(actions) {
const dispatch = useDispatch();
return useMemo(() => {
return bindActionCreators(actions, dispatch);
}, [actions, dispatch]);
}
/* use-counter */
import { useMemo } from "react";
import { useSelector } from "react-redux";
import { decrement, increment, set } from "./actions";
import { useActions } from "./use-actions";
export const useCounter = () => {
const count = useSelector((state) => state.count);
const actions = useActions({ increment, decrement, set });
return useMemo(() => {
return { count, ...actions };
}, [count, actions]);
};
import { SetCounter } from "./SetCounter";
import { useCounter } from "./use-counter";
export const Counter = () => {
const incident = "Incident";
const { count, increment, decrement, set } = useCounter(); /* 🌝 */
return (
<main className="Counter">
<h1>Days Since Last {incident}</h1>
<p className="count">{count}</p>
<section className="controls">
<button onClick={() => increment()}>Increment</button>
<button onClick={() => set(0)}>Reset</button>
<button onClick={() => decrement()}>Decrement</button>
</section>
<SetCounter />
</main>
);
};
export default Counter;
구현이 간단하다는 장점이 있지만 UI 컴포넌트에 서비스 로직이 합쳐지기 때문에 비교적 테스트하기 어렵고 디자인 시스템으로 UI layer를 별도로 분리해서 관리하기 힘들다는 단점이 있습니다.
- connectAPI
HoC 패턴의 connect() 함수를 통해 스토어의 상태를 Presentational Component에 주입하여 사용할 수 있습니다.
import { connect } from "react-redux";
import { MenuItems } from "../components/MenuItems";
const mapStateToProps = (state) => {
return {
items: state.items,
};
};
export const MenuItemsContainer = connect(mapStateToProps)(MenuItems);
마찬가지로 dispatch 함수를 props로 연결해서 제공합니다.
import { connect } from "react-redux";
import { NewItemForm } from "../components/NewItemForm";
import { addNewItem } from "../store/items/reducer";
const mapDispatchToProps = (dispatch) => {
return {
onSubmit: (name, price) => dispatch(addNewItem(name, price)),
};
};
export const NewItemFormContainer = connect(
null,
mapDispatchToProps
)(NewItemForm);
redux의 bindActionCreators 함수 적용 예시
const mapDispatchToProps = (dispatch) => {
return bindActionCreators(
{
onSubmit: addNewItem,
},
dispatch
);
};
비교적으로 구현할 내용의 분량이 있고, Container Component와 Presentational Component로 분리해야하는 단점이 있지만, 서비스 로직과 UI Layer를 분리하여 디자인 시스템에 적용하거나 테스트하기 좋은 컴포넌트라는 장점이 있습니다.
🌼 Design
🌷 Daily scrum
[Daily scrum] 21.10.27
[Daily scrum] 21.10.28
[Daily scrum] 21.10.29
[Daily scrum] 21.11.02
[Daily scrum] 21.11.03
[Daily scrum] 21.11.04
[Daily scrum] 21.11.09
[Daily scrum] 21.11.10
[Daily scrum] 21.11.11
[Daily scrum] 21.11.16
[Daily scrum] 21.11.17
[Daily scrum] 21.11.18
[Daily scrum] 21.11.23
[Daily scrum] 21.11.24
[Daily scrum] 21.11.25
[Daily scrum] 21.11.30
[Daily scrum] 21.12.01
[Daily scrum] 21.12.02