본문 바로가기

공부기록/[강의노트] Udemy React 완벽가이드 201~300

# 249 [udemy React 완벽 가이드 노트] 토글 카운터 버튼 활성화 (중요: 절대 기존의 state를 변형하지 말것 )

toggle counter button을 누르면

counter button이 사라지거나 보이게 한다. 

이것은 redux로 관리하는 것보다는 

useState로 관리하는 것이 낫다. 

 

local state이기 때문이다. 

즉, state는 지금 컴포넌트 에서만 사용할 것이다. 

 

그런데 연습을 위해 

Counter와 state 모두가 

Counter가 보여야 할지말지를 정한다고 가정하자.

즉, global state임을 가정하자.  

 

 

toggle 버튼을 클릭해서 액션을 디스패치 하고 

리덕스에서 state를 변경한다. 

그건 counter가 보이는 div태그를 보이게 할지 말지 제어한다. 

 

 

리덕스 스토어에 새 정보를 추가하자. 


counterReducer로 가서 모든 state 스냅샷을 추가한다. 

 

 

 

initialState snapshot

 

const counterReducer = (state = { counter: 0, showCounter: true }, action) => {

 

 

 

 

가독성을 높이기 위해 initialState로 추출해서 할당한다.

 

 

const initialState = { counter: 0, showCounter: true };

const counterReducer = (state = initialState, action) => {

 

 

 

 

 

counterReducer function 변경

 

 

리덕스는 initial State에서 변화된 것을 합치치 않는다.

action.type에서 return된 객체로 기존의 것을 대체할 뿐이다. 

그러므로 기존의 showCounter value를 넣을 함수인

showCounter: state.showCounter로 채워넣자. 

increment 일 때는 showCounter를 변경하고 싶지 않기 때문이다. 

 

마찬가지로 decrement와 increase 일 때도 해주자.

 

그리고 action.type을 toggle일 때도 추가해 준다. 

 

const counterReducer = (state = initialState, action) => {
  if (action.type === "increment") {
    return {
      counter: state.counter + 1,
      showCounter: state.showCounter,
    };
  }

  if (action.type === "decrement") {
    return {
      counter: state.counter - 1,
      showCounter: state.showCounter,
    };
  }

  if (action.type === "increase") {
    return {
      counter: state.counter + action.amount,
      showCounter: state.showCounter,
    };
  }

  if (action.type === "toggle") {
    return {
      showCounter: !state.showCounter,
      counter: state.counter,
    };
  }

 

toggle일 때는 기존의 showCounter 상태와 반대여야 하므로 ! exclamation mark를 사용하고 

counter는 기존의 상태를 유지해야 하므로 state.counter로 그대로 놓도록 한다. 

 

 

이제 리덕스에서 toggle타입을 지원해 준다. 

Counter컴포넌트에서 useSelector로 showCounter의 상태를 가져온다. 

그리고 show가 truthy일 때만 counter div 태그를 보여준다. 

 

 

  const show = useSelector(state => state.showCounter);
  ...     
  {show && <div className={classes.value}>{counter}</div>}

 

 

 

하면 안되는 예시들

 

 

하면 안되는 예시

 

 

const counterReducer = (state = initialState, action) => {
  if (action.type === "increment") {
  
    state.counter++

    return state
  }

 

 

 

제대로 작동되는 것처럼 보이지만 잘못된 코드다. 

 

리덕스로 작업할 때는 이렇게 하면 안된다.  

 

 

 

 

*****중요 : 절대 기존의 state를 변형해서는 안 된다 *****

 

대신 새로운 state 객체를 반환하여 재정의 해야 한다.

객체와 배열은 자바스크립트에서 참조 값이기 때문에

뜻하지않게 기존의 state를 재정의하거나 변경하기 쉽다. 

 

 

 

하면 안되는 예시 2

 

 

const counterReducer = (state = initialState, action) => {
  if (action.type === "increment") {
    state.counter++
    
    return {
      counter: state.counter,
      showCounter: state.showCounter,
    };
  }

 

이미 return 이전에 state.counter를 더했기 때문에

그대로의 state.counter를 counter에 재정의 하면 될것만 같다. 

그러나 이것도 좋지 않은 예시다. 

 

객체 배열이 

자바스크립트에서 참조값이기 때문에 

여전히 기존의 state를 변형시키고 있는 코드다. 

 

 

버그로 예측 불가능한 동작이 발생할 수 있고, 

프로그램 디버깅도 어려워 질 수 있다.