[React] Redux 기초 문법(2) - reducer, dispatch 함수
지난 블로깅에서는 state를 저장하고 사용하는 방법만 알아보았고,
이번시간에는 데이터 수정하는 방법에 대해서 알아보도록 하자.
reducer 함수
state 데이터의 수정방법을 미리 정의하는 함수이다.
state 초기값과 데이터 수정방법을 넣는다. function reducer(state = 초기값, 액션)
1. '수량증가'라는 데이터 수정방법 이름을 작명해서 넣어준다. (액션.type === 수정방법이름)
2. if문 안에 '수량증가'라는 요청이 들어올 경우 else if문에는 '수량감소'라는 요청이 들어올 경우 수정방법 정의.
3. else문 안에는 둘 다 안들어온 경우 기본 state를 결과값으로 가져올 것을 수정방법 정의.
index.js
let 초기값 = [
{id: 0, name: '멋진신발', quan : 2},
{id: 1, name: '멋진신발2', quan : 1}
];
function reducer(state = 초기값, 액션){
if(액션.type === '수량증가'){
let copy = [...state];
copy[0].quan++;
return copy
} else if(액션.type === '수량감소'){
let copy = [...state];
copy[0].quan--;
return copy
} else{
return state
}
}
reducer가 더 필요하면
reducer가 여러개 필요하면 다른 이름의 reducer2 + reducer2의 초기값을 하나 더 만들고
combineReducers()라는 함수안에 집어넣은 후에 createStore()안에 넣으면 된다.
index.js
import {combineReducers, createStore} from 'redux';
let alert초기값 = true;
function reducer2(state = alert초기값, 액션){
if(액션.type === 'alert닫기'){
state = false;
return state;
} else{
return state
}
}
let 초기값 = [
{id: 0, name: '멋진신발', quan : 2},
{id: 1, name: '멋진신발2', quan : 1}
];
function reducer(state = 초기값, 액션){
if(액션.type === '수량증가'){
let copy = [...state];
copy[0].quan++;
return copy
} else if(액션.type === '수량감소'){
let copy = [...state];
copy[0].quan--;
return copy
} else{
return state
}
}
let store = createStore(combineReducers({reducer,reducer2}));
Cart.js
{ props.alertClose === true
? (<div className="my-alert-pink">
<p>지금 구매하시면 신규할인 20%</p>
<button onClick={()=>{props.dispatch({ type: 'alert닫기' }) }}>X</button>
</div>)
: null
}
function state를props화(state){
return {
state : state.reducer,
alertClose : state.reducer2
}
}
dispatch 함수
dispatch()를 사용하면 HTML 안에서 reducer함수를 동작시킬 수 있다.
즉, 위의 '수량증가', '수량감소' 데이터 수정방법을 실행하는 것을 명령하기 위해 사용하는 함수이다.
dispatch({ type:데이터수정방법 }) 만 잘 지정해주면 된다.
Cart.js
<tbody>
{
props.state.map((a,i)=>{
return (
<tr key={i}>
<td>{ a.id }</td>
<td>{ a.name }</td>
<td>{ a.quan }</td>
<td>
<button onClick={()=>{ props.dispatch({ type: '수량증가'}) }}>+</button>
<button onClick={()=>{ props.dispatch({ type: '수량감소'}) }}>-</button>
</td>
</tr>
)
})
}
</tbody>
한줄 요약하자면 reducer 함수를 만들고 수정하는 방법을 정의한 뒤 dispatch() 함수를 통해 데이터를 수정하면 된다.
dispatch 함수의 다른 기능
지금까지 dispatch 함수를 이용하여 데이터 수정방법을 배웠지만 props.dispatch({ type: '항목추가', payload: {데이터들} }); 이런식으로 데이터를 redux store까지 데이터를 실어보낼 수 있고 reducer 안에서 요청을 처리할 땐 액션.payload라고 쓰면 보냈던 데이터를 사용할 수 있다. 액션이라는 파라미터는 reducer(state, 액션) {} 에서 dispatch() 소괄호 안에있던 모든게 들어있다. 그래서 payload 말고도 여러가지 정보들을 함께 보낼 수 있다.
reducer 함수에 데이터 수정하는 방법 '항목추가'를 정의한다.
'항목추가'라는 요청이 들어오면 카피본을 생성해서 전송받은 데이터를 push (array에 추가) 해주세요라는 뜻.
payload에 적혀 있는 데이터가 채워넣어진다. (reducer에서 그 데이터를 state에 추가)
index.js
function reducer(state = 초기값, 액션){
if(액션.type === '항목추가'){
let copy = [...state];
copy.push(액션.payload);
return copy;
} else if(액션.type === '수량증가'){
let copy = [...state];
copy[0].quan++;
return copy
} else if(액션.type === '수량감소'){
let copy = [...state];
copy[0].quan--;
return copy
} else{
return state
}
}
Detail.js
<button className="btn btn-danger" onClick={()=>{
props.dispatch({type : '항목추가', payload: {id:2, name:'새로운상품', quan:1} });
history.push('/cart');
}}>주문하기</button>
주문하기 버튼을 누를 때 payload라는 항목의 데이터가 redux store로 전달하는 dispatch 기능을 추가한다.
history.push() 등의 라우터 함수를 이용해서 페이지 이동을 강제로 시키면 개발환경에서도 초기화 (state 리셋) 되지 않는다.
function state를props화(state){
return {
state : state.reducer,
alertClose : state.reducer2
}
}
export default connect(state를props화)(Detail)
참고로 props.dispatch를 그냥 쓰면 에러나기 때문에 꼭 컴포넌트 파일 하단에 connect를 해줘야 한다.
(물론 connect 함수도 위에서 import 해와야 함)
Redux는 왜 사용하는가?
위의 Redux 첫번째 포스팅에서 Redux를 사용하는 첫번째 이유가
복잡한 props 전송없이 모든 컴포넌트가 직접 데이터를 꺼내쓸 수 있다는 것이었다면,
두번째 이유는 reducer, dispatch 함수를 사용하면 state 데이터 관리(일명 상태관리)가 용이하기 때문이라고 말할 수있다.