본문 바로가기
fastcampus

[패스트캠퍼스 수강 후기] 프론트엔드 인강 100% 환급 챌린지 27회차 미션

by 새우하이 2020. 10. 3.

 

리듀서 immer 로 구현하기.

CREATE_USER, TOGGLE_USER, REMOVE_USER 액션들에 대해 immer를 사용해서 구현해 줄 것이다.
immer를 사용한다고 해서 무조건 코드가 깔끔해지는 것은 아니다.

.
.
// App.js
  case 'CREATE_USER':
      return produce(state, draft =>{
        draft.users.push(action.user)
      });

    case 'TOGGLE_USER':
      return produce(state, draft =>{
        const user = draft.users.find(user => user.id === action.id);
        user.active = !user.active;
      })
      // return{
      //   ...state,
      //   users: state.users.map(user =>
      //     user.id === action.id ?{...user,active: !user.active}
      //     :user
      //     )
      // };
    case 'REMOVE_USER':
      return produce(state, draft => {
        const index = draft.users.findIndex(user => user.id === action.id);
        draft.users.splice(index, 1);
      });
      // return{
      //   ...state,
      //   users: state.users.filter(user => user.id !== action.id)
      // }

기존에 구현했던 코드들을 지워주고, immer를 사용해서 구현해본다.
state와 draft를 넣어주고 draft를 받아오는 함수에서는 draft.users에 action.user를 push해준다. 사실상 보면 immer를 안 쓴것이 더 깔끔해보인다.

TOGGLE_USER에서도 마찬가지로 draft의 users find 로 해당 user들 중에서 user.id 가 action으로 가져온 id 와 같은 사용자 정보를 찾아서 , user가 지니고 있는 active 값을 반전 시켜준다.

REMOVE_USER은 인덱스를 먼저 찾아준다 immer 에서는 splice라는 함수를 사용해서 배열에 있는 원소를 없앨 수 있는데, splice를 사용하려면 index값을 알고 있어야한다. findIndex를 사용해서 user.id 가 action.id 인것을 찾아서 splice를 통해 index부터 1개를 없애겠다고 정의한다.

여기까지 코드를 실행해보면 모두 정상적으로 작동할 것이다.

우리가 이전에 useState를 사용할 때 함수형 update를 사용 할 수 있다고 배웠다.
예를들어 setTodo에다가 다음 상태를 넣어주는 것이 아니라 어떻게 update할 것인지 정의하는 코드를 넣어줄 수 있었다. 그렇게 했을 때는 우리가 useCallback을 사용하게 될 때, 위에 선언된 todo 상태를 의존하고 있기 때문에 넣어줘야했지만 함수형 update를 사용할 때는 deps배열에 기존 todo를 넣어 줄 필요가 없다.
만약 함수형 업데이트를 하는 경우에 immer를 사용하면 상황에 따라 더 편하게 업데이트해 줄 수 있다.

const todo ={
    text: 'hello',
    done: false
};

const updater = produce(draft => {draft.done = !draft.done;
});

const nextTodo = updater(todo);

console.log(nextTodo);

기존에 immer를 사용 할 때state와 draft를 파라미터로 사용했지만, state 없이 함수만 넣어주면 이 produce의 결과물은 updater 함수가 된다. 이 updater의 결과가 하나의 함수이기 때문에 만약
const nextTodo = updater(todo);
를 실행하면 nextTodo의 값은 업데이트가 된다.

const [todo, setTodo] = useState({
    text: 'hello',
    done: false
});

const onClick = useCallback(()=>
    setTodo(
        produce(draft =>{
            draft.done = !draft.done;
        })
    );
},[]);

그래서 produce에 파라미터를 함수 하나만 넣게되면 updater가 반환된다는 것이다.이것을 활용해서 결국 produce가 반환하는것이 updater함수가 되면, useState를 사용해서 만들어진 setTodo에다가 파라미터에 updater함수를 넣을 수 있게된다.
이렇게하면 불변성을 유지하면서, 특정 업데이트를 할 수 있게된다.

useState를 사용해서 까다로운 객체를 관리해야하는데, 불변성 관리하기가 까다로운 경우에 produce가 updater반환하는 특성을 사용해서 코드를 작성하면 편할 수 있다.

immer performance를 보면 immer가 조금 느린것 처럼 보이지만, 실제로 사용자가 인지할 수 있는 정도의 차이는 아니고, 데이터의 양이 500k정도 됐을 때 저정도의 차이이므로 큰 걱정 없이 사용해도 된다.

class 형 컴포넌트

우리가 기존에 컴포넌트를 만들 때에는 함수형으로 만들었다.
class형 컴포넌트는 컴포넌트를 선언하는 또 다른 방식이다. 요즘 잘 사용하지는 않는다.
하지만 class형 컴포넌트를 사용하는 프로젝트를 유지보수 할 수도 있기 때문이다.

class형 컴포넌트를 만들기위해 Hello 컴포넌트를 열어 본다.

// Hello.js

// function Hello({color, name, isSpecial}){
//     return <div style={{color}}>
//         {isSpecial ? <b>*</b> : null}
//         ㅎㅇ {name}</div>;
// }

그리고 기존에 함수형으로 작성했던 Hello컴포넌트를 주석처리해준다.
class 형 컴포넌트를 사용하기 위해서는, {Component} 를 따로 불러와야하고, class라는 키워드를 사용해서 컴포넌트를 선언하고
render() 라는 메서드가 있어야한다. 그리고 이 내부에서는 JSX를 반환해 줘야한다.
밑에 구현했던 로직을 동일하게 구현해준다.

class Hello extends Component{
    render(){
        const{ color, isSpecial, name} = this.props;
        return(
            <div style={color}>
                {isSpecial && <b>*</b>}
                안녕하세요 {name}
            </div>
        );
    }
}

비구조 할당을 통해서 this.props에 있는 color, isSpecial, name을 추출해 주고, 사용하면 좀 더 간결하게 사용할 수 있다.

여기서 defaultProps 를 설정하게 될 때에는 또 다른 방식으로
class 형 컴포넌트에서 static defaultProps를 사용하는 방법도 있다.

// Hello.js
// Hello.defaultProps={
//     name: 'default name'
// }

해당 구문을 주석처리해주고
Hello 클래스 컴포넌트에서

// Hello.js
class Hello extends Component{
    static defaultProps ={
        name : '이름없음',
    }
    render(){
        const{ color, isSpecial, name} = this.props;
        return(
            <div style={color}>
                {isSpecial && <b>*</b>}
                안녕하세요 {name}
            </div>
        );
    }
}

로 설정해주고
index.js에서 Hello컴포넌트로 바꿔주고

로 설정해주면 잘 작동하는 것을 볼 수 있다.

 

해당 내용은 아래 링크에서 수강할 수 있다.

프론트엔드 개발 올인원 패키지 with React Online. 👉https://bit.ly/2ETLEzm

 

프론트엔드 개발 올인원 패키지 with React Online. | 패스트캠퍼스

성인 교육 서비스 기업, 패스트캠퍼스는 개인과 조직의 실질적인 '업(業)'의 성장을 돕고자 모든 종류의 교육 콘텐츠 서비스를 제공하는 대한민국 No. 1 교육 서비스 회사입니다.

www.fastcampus.co.kr

 

댓글