이번 시간에는 state 값을 변경시키는 방법을 살펴보겠습니다.
우선 다른 부품들을 직접적으로 제어하는 fire라는 코드를 변경시키겠습니다.
<input type="button" value="fire" onclick="
store.dispatch({type:'CHANGE_COLOR', color:'red'});
">
store에게 dispatch() 함수를 호출하면서 객체를 하나 주는데 그 객체에서 가장 중요한 property는 type입니다
store에 dispatch() 를 호출하면 dispatch는 store를 생성할 때 제공한 reducer() 함수를 호출하도록 약속되어 있습니다.
그때 이전의 state 값과 전달된 action 값을 인자로 전달합니다.
우리 코드에서는 {type:'CHANGE_COLOR', color : 'red'} 이 action 값입니다.
console.log(state,actinon); 를 실행시켜 보겠습니다.
실행했을 때 undefined라고 나오는 것은 최초 한번 무조건 실행된 것이고
fire 버튼을 누르면 dispatch에서 action 값이 전달되고 이전의 state값과 action의 값이 들어옵니다.
return 되는 값을 {color : 'red'} 로 변경하면 fire 버튼을 눌렀을 때 state 값이 교체됩니다.
콘솔창에 store.getState()를 실행하면 {color : 'red'} 가 됩니다.
reducer 는 이전 상태의 state와 action 값을 받아서 다음 상태의 state 값을 리턴해줍니다.
function reducer(state, action){
console.log(state, action);
if(state === undefined){
return {color:'yellow'}
}
if(action.type === 'CHANGE_COLOR'){
state.color='red';
}
return state;
}
위의 코드처럼 작성해서 실행해도 color : 'red' 로 바뀌는 것을 볼 수 있습니다.
하지만 이렇게 하면 시간여행 그리고 REDO와 UNDO같은 혜택을 누릴 수가 없습니다.
현재의 store의 state 값을 변경해서 리턴하지 말고 state 값을 복제한 복사본을 리턴하면 됩니다.
그러면 시간여행, REDO와 UNDO 를 할 수 있고, 애플리케이션이 예측 가능하도록 동작하게 할 수 있습니다.
객체를 복제할 때는 Object.assign() 이라고 하는 명령을 이용합니다.
이때 첫 번째 인자로 반드시 기 빈 객체를 줍니다. 두 번째 인자로는 이 빈 객체의 복제할 속성을 가진 객체를 줍니다.
예를 들면 Object.assign({},{name:'egoing'}); 명령을 실행하면 빈 객체에 name 속성은 'egoing' 이라고 하는 값을 복제합니다.
그리고 Object.assign({},{name:'egoing'},{city:'seoul'}); 이라고 수정하면 {city:'seoul'} 값도 복사하는 것입니다.
첫 번째 인자에 두번째 인자를 복사하고 그 결과에 다시 세 번째 인자를 복사해서
{name:'egoing' , city:'seoul'} 이라고 하는 새로운 객체가 복사됩니다
첫번째 인자로 빈 객체를 줘야하는 이유는 Object.assign() 함수의 리턴 값은 첫 번째 인자인 객체이기 때문입니다.
function reducer(state, action){
console.log(state, action);
if(state === undefined){
return {color:'yellow'}
}
var newState;
if(action.type === 'CHANGE_COLOR'){
newState = Object.assign({}, state, {color:'red'});
}
return newState;
}
이렇게 코드를 적용해보면 state의 property 들이 첫 번째 인자인 빈 객체에 복제되서 복사본 newState가 리턴됩니다.
그리고 세번째 값으로 {color : 'red'} 를 주게 되면 복사본에 또 복제 되는 것입니다. 그렇게 만들어진 최종적인 결과를 리턴합니다.
즉 reducer() 함수가 실행될 때마다 각각의 새로운 state 값들이 서로 완전히 독립된 복제된 결과들을 리턴하게 됩니다.
코드를 바꾸고 실행시켜 콘솔창에 store.getState() 함수를 호출하면 결과는 {color : 'red'} 가 됩니다.
reducer() 함수가 하는 역할은 action의 값과 이전의 state 값을 이용해서 store의 새로운 state 값이 된다는 것이 핵심입니다.
그리고 새롭게 리턴되는 값은 원본을 바꾸는 것이 아니라 이전에 있었던 값을 복제한 결과를 리턴하는 것입니다.
이렇게 해서 리덕스르 통해 사용하는 여러가지 효용들을 최대한으로 활용할 수 있는 것입니다.
생각해보기
reducer의 역할에 대해 설명해보세요.