본문 바로가기
2022년

2021/07/14 - CodeReview

by 박상윤 2021. 7. 14.

Project : 달력과 연동되는 가계부 만들기 / BCSD team project

 

(1)  CustomHook을 바로 JSX내부에서 사용하지말고, 함수 컴포넌트에 선언을 하고, 사용을 하자

<BlueButton active={type} value={'INCOME'} onClick={clickBtn}>+{useGiveSum('INCOME',month,year)}</BlueButton>
<RedButton active={type} value={'EXPEDITURE'} onClick={clickBtn}>{useGiveSum('EXPEDITURE',month,year)}</RedButton>

useGiveSum이라는 customHook은 type = {수입,지출}에 따라 수입의 총합, 지출의 총합을 return해준다.

위와같은 방식으로 불러온 customHook을 바로 사용해주는 것보다 변수를 새로 하나 선언을 해서 그 변수에 useGiveSum에서 return되는 값을 재사용하는 식으로 수정을 하자

 

incomeSum = useGiveSum('INCOME',month,year);
expeditureSum = useGiveSum('EXPEDITURE',month,year);

incomSum과 expeditureSum이라는 변수를 선언하고 useGiveSum을 각 타입에 맞게 사용해주었다.

<BlueButton active={type} value={'INCOME'} onClick={clickBtn}>+{incomeSum}</BlueButton>
<RedButton active={type} value={'EXPEDITURE'} onClick={clickBtn}>{expeditureSum}</RedButton>

 

결론

useGiveSum('INCOME',month,year)로 바로사용했던 값을 incomeSum과 expeditureSum이라는 새로운 변수를 선언해서 사용해주었다.

 

(2) Redux의 CombineReducers를 사용할때, 사용되는 Reducer의 이름을 변경하지말고 Reducer이름을 그대로 사용해주자

import { incomeExpeditureReducer} from './reducers/incomeExpeditureReducer';
import { showListReducer } from './reducers/showListReducer';

const reducers = combineReducers(
    {   IE:incomeExpeditureReducer,
        SH:showListReducer,
    }
);

incomeExpeditureReducer와 showListReducer를 combineReducers를 이용해서 하나의 reducers로 만들어 준다. 이 reducers를 만들어 줄때, 든 생각은 "각 Reducer의 이름을 좀더 함축적으로 축약해서 적어놓으면, store에서 데이터 가져올경우, 짧은 단어를 통해 더 간단하게 가져올 수 있겠다." 라는 생각에서 incomeExpediture와 showListReducer를 각각 IE와 SH로 정의해주었다.

나만 프로젝트를 만드는 상황이라면, 이렇게 함축적으로 정의해주는 것은 상관없지만, 혼자하는 것이아닌 팀프로젝트로 하기때문에, 가독성 측면에서 내가 아닌 다른이가 알아볼 수 없는 단어가 된다. 또한 Redux 공식문서에서 나온 예시에서도 reducer의 이름을 재정의해주지 않고, 기존에 만들어 주었던 Reducer의 이름을 그대로 사용해준다.

 

const reducers = combineReducers(
    {   incomeExpeditureReducer,
        showListReducer,
    }
);

ES6에서는 incomeExpeditureReducer만 써주게 되면, incomeExpeditureReducer:incomeExpeditureReducer와 같은 의미를 갖는다.

 

(3) ES6 : 구조 분해 할당을 사용하라

 

구조 분해 할당이란?

배열이나 객체의 속성을 해체하여 그 값을 개별 변수에 담을 수 있게 하는 JavaScript표현식이다.(MDN참고)

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment

간단히 적용해보기

출력결과

코드 수정에 사용될 MDN 문서 내용

 

변경 전

const lists = useSelector((state)=>(state.incomeExpeditureReducer).list);

let type = useSelector((state)=>(state.showListReducer).type);
let month = useSelector((state)=>(state.showListReducer).month);
let year = useSelector((state)=>(state.showListReducer).year);

변경 후

const {list:lists} = useSelector((state)=>(state.incomeExpeditureReducer));
let {type,month,year} = useSelector((state)=>state.showListReducer);

변경 전과 변경 후를 비교해보았을 때, 굉장히 깔끔한 것을 알 수 있다. 구조 분해 할당을 앞으로 계속 써야겠다.

 

(4) 불변성을 지키자

let {type,month,year} = useSelector((state)=>state.showListReducer);
    
    const showMonth = (e) => {
        const direction = e.target.parentNode.value;
        if(direction==='right'){
            month+=1;
            if(month===12){
                month=0;
                year+=1;
            }
        }else{
                month-=1;
            if(month===-1){
                month=11;
                year-=1;
            }
        }
        dispatch(Month(month));
        dispatch(Year(year));
    }

https://redux.js.org/faq/immutable-data

 

불변성의 이점은 무엇일까?

변경되지 않는 데이터가 앱 전체에서 임의로 변경할 수 있는 데이터보다 추론하기가 더 쉽기 때문에 불변성은 앱의 성능을 향상시키고, 프로그래밍 및 디버깅을 단순화할 수 있다.(Redux공식문서 참조)

 

    let {type,month,year} = useSelector((state)=>state.showListReducer);
    let newMonth = month;
    let newType = type;
    let newYear = year;
    
    const showMonth = (e) => {
        const direction = e.target.parentNode.value;
        if(direction==='right'){
            newMonth+=1
            if(month===11){
                newMonth=0;
                newYear+=1;
            }
        }else{
            newMonth-=1;
            if(newMonth===-1){
                newMonth=11;
                newYear-=1;
            }
        }
        dispatch(Month(newMonth));
        dispatch(Year(newYear));
    }
    
const clickBtn = (e) => {
        const value = e.target.value;

        if(type==='INCOME'||type==='EXPEDITURE'){
            type = 'incomeExpediture';
        }else{
            newType = value;
        }
        dispatch(Type(newType));
    }

type,month,year라는 변수는 Redux의 store로 부터 useSelector를 사용하여 값을 받아온다.

물론, type,month,year라는 변수를 직접 수정한후, 최종적으로 dispatch를 해도 상관은 없지만, Redux의 store로 부터 받아온 데이터인 만큼 Immuatble을 지켜주고자 newMonth, newType, newYear라는 변수를 따로 선언해주었다. 값이 변경될 일이 있으면 newMonth,newType,newYear라는 변수의 값을 변경한 후, dispatch를 해준뒤, store에 존재하는 type,month,year을 최종적으로 변경시켜주도록 하였다.

 

(5) JSX에서 불필요하게 생성되는 태그들을 삭제하자

{newLists.map((list)=>{
                return(
                    <div key={list.id}>
                        <Datelist>
                                {checkDate(list.date)?`${list.day}, ${list.date}th`:''}
                        </Datelist>
                        <ListWrapper> 
                            <List>
                                <Label>{list.label}</Label>
                                <Amount active={list.amount}>{list.amount>0?`+${transformation(list.amount)}`:transformation(list.amount)}</Amount>
                            </List>
                        </ListWrapper>
                    </div>
                );
            })}

Datelist라는 styledcomponent 태그 안에 있는 내용들은 조건을 만족하게되는 경우, 값이 나타나는 부분이다.

Datelist는 div태그를 사용해서 만든 부분으로 조건을 만족하지 않아도 불필요하게 UI에 등장을 하게된다.

맨 위에 있는 UI는 WEN,14th라는 출력값이 존재하지만, 밑에 있는 UI는 출력값이 존재하지 않는다. 출력값이 존재하지 않음에도 불구하고, 밑에 있는 UI는 쓸데없는 div태그를 가지게 된다. 이제 이 div 태그를 없애주자

 

{newLists.map((list)=>{
                return(
                    <div key={list.id}>
                                {checkDate(list.date)?(
                                    <Datelist>
                                        {list.day}, {list.date}th
                                    </Datelist>
                                ):''}
                        <ListWrapper> 
                            <List>
                                <Label>{list.label}</Label>
                                <Amount active={list.amount}>{list.amount>0?`+${transformation(list.amount)}`:transformation(list.amount)}</Amount>
                            </List>
                        </ListWrapper>

삼항 연산자에 JSX를 사용해주어서 데이터가 UI에 등장할 경우에만 styled component인 Datelist(div)를 출력해주었다.

 

불필요한 div태그가 사라졌다!

 

(6) Redux를 통해 관리되는 list들의 id 값도 리덕스에서 관리하자

export const init = ()=>{
    const getlist = JSON.parse(localStorage.getItem('lists'));
    const list = getlist?getlist:[];
    let incomeId = 0;
    let expeditureId = 0;

    if(checkLocal()){
        incomeId = getId('INCOME',0);
        expeditureId = getId('EXPEDITURE',100);
    }
    

    return {
        type:INIT,
        list,
        incomeId,
        expeditureId
    }
}

action 생성 함수 init을 사용해서 list들에 사용될 id 값을 Redux로 상태관리를 해줄 수 있게 변경함

DataBase가 아닌 localStorage에 데이터를 저장하는 형태로 하기때문에, 이미 데이터가 저장이 되어있는 경우, localStorage.getItem을 이용해서 저장된 리스트의 마지막 id값을 가져와준다음 이어서 사용하도록 구현함

 

localStorage에 키가 lists인 value가 있는지 없는지 확인해주는 함수

export const checkLocal  = () => {
    if(localStorage.getItem('lists')){
        return true;
    }else {
        return false;
    }
}

값이 존재한다면, lists의 마지막 list의 id값을 가져와주는 함수

export const getId = (type,value) => {
    let id = value;
    const lists = JSON.parse(localStorage.getItem('lists'))
    .filter((list)=>list.type===type);
    
    if(lists.length!==0){
        id = ++lists[lists.length-1].id;
    }
    return id;
}

Reducer

case INIT:
            return {
                list:action.list,
                incomeId:action.incomeId,
                expeditureId:action.expeditureId
            }

(7) li태그들을 그냥 냅두지 말고, ul태그로 감싸자

<UlWrapper>
                {newLists.map((list)=>{
                    return(
                        <div key={list.id}>
                                    {checkDate(list.date)?(
                                        <Datelist>
                                            {list.day}, {list.date}th
                                        </Datelist>
                                    ):''}
                            <ListWrapper> 
                                <List>
                                    <Label>{list.label}</Label>
                                    <Amount active={list.amount}>{list.amount>0?`+${transformation(list.amount)}`:transformation(list.amount)}</Amount>
                                </List>
                            </ListWrapper>
                        </div>
                    );
                })}
</UlWrapper>

styled component를 이용해서 UlWrapper를 만들어주었고 만든 UlWrapper을 li태그들을 만들어내는 부분을 감싸주었다.

 

'2022년' 카테고리의 다른 글

Parameter vs Argument  (0) 2021.07.15
최대 매출(Sliding Window)  (0) 2021.07.15
CustomHook만들어 사용하기  (0) 2021.07.14
useState 상태관리 >> Redux 상태관리로 변경  (0) 2021.07.14
React - useReducer  (0) 2021.07.13