useReducer 는, 강력한 State 관리 도구이다.
useState 에 비해, 조금 복잡하지만, 많은 state의 변화를 가져오는 action (실행 함수) 을 한군데 모아,
가독성 있게 State 를 관리 할 수 있다.
또한, 컴포넌트의 상태 업데이트 로직을 컴포넌트에서 분리시킬 수 있다.
useReducer는, 크게 두가지 파트가 있다.
리듀서 함수, 그리고 리듀서함수를 dispatch 하여 사용하기
1. 리듀서함수
리듀서 함수는, type 이라는 action의 이름을 이용하여, 각 type 에 맞는, action을 취하게 한다.
리듀서 함수의 반환값 (쉽게 말하면, 각각의 type에 맞는 action이 일어난 후 return 값) 은, 새로운 상태 를 반환한다.
* 리듀서함수는 컴포넌트 함수 밖에서 정의할 수 도 있다(대부분 그렇다)
2. 리듀서함수의 dispatch
각 type 에 맞는 action을, 리듀서 함수에 정의했다면,
컴포넌트 함수 내부에서, dispatch 를 통해, type 프로퍼티 에 접근하여, 그 action을 가져올 수 있다.
액션이 실행되면, 리듀서함수에서 정의한 action의 return ( 사실 리듀서 함수의 return ) 을 새 상태로 가져온다.
3. 기본 정의
자세히 알아보자
[기본]
< 1. 리듀서함수의 정의 >
function reducerFn(state, action){ => 리듀서함수는, "현재상태"와 "액션"을 파라미터로 받아와서 "새로운 상태를 반환해주는 함수"
retrun nextState => 리듀서 함수의 반환값은 곧, "새로운 상태"
}
* state : 현재 상태
* action : "type" 값이 존재하고, "나머지는 맘대로 무엇이든 넣을 수 있는", "객체형태"의 코드
type 은 보통, "대문자", "_" 를 사용한다.
<리듀서 함수 예시> ============================================================
=> "취할 모든 액션을 정의한다."
function reducer(state, action) { // 무엇이든, "action.type"을 확인하여, "원하는 action"을 취하게한다.
if (action.type == "INCREMENT") {
return state + 1; // 반환에는, "state" 를 변화시킨다.
}
if(action.type == "DECREMENT") {
return state - 1;
}
}
<< 2. 컴포넌트 함수 내에서, 정의한 "리듀서함수"를 가져와서 사용하기 >>
function Counter(){
const [number, dispatch] = useReducer(reducerFn, 0);
function OnIncrease(){
dispatch({type: 'INCREMENT' })
}
function OnDecrease(){
dispatch({type: 'DECREMENT' })
}
retrun (
<div>
<button onClick={OnIncrease}> +1 </button>
<button onClick={OnDecrease}> -1 </button>
</div>
)
}
<< 3. 결합 >>
import React, { useReducer } from 'react';
function reducer(state, action) {
switch (action.type) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
}
function Counter() {
const [number, dispatch] = useReducer(reducer, 0);
const onIncrease = () => {
dispatch({ type: 'INCREMENT' });
};
const onDecrease = () => {
dispatch({ type: 'DECREMENT' });
};
return (
<div>
<h1>{number}</h1>
<button onClick={onIncrease}>+1</button>
<button onClick={onDecrease}>-1</button>
</div>
);
}
export default Counter;
1. useReducer는 리듀서함수, 초기값, 초기함수 를 파라미터로 갖는다
2. 리듀서함수는, state와, action 을 파라미터로 갖는다.
3. 리듀서함수는, "반환값으로" , "변할 State 를 갖는다" [ useState 의 setValue() 처럼]
4. 리듀서함수는, "실행 될 action"을 "전부 적고", "type" 에 따라, "다른 action을 취하도록 한다".
5. 리듀서함수의 action(실행함수) 를 사용하기 위해, "dispatch" 명령어로,
"action 안에 정의한 객체 프로퍼티 type 을 가져온다." [type == id(불러올때 쓸 이름)]
6. "dispatch"로 "특정 type을 정하여", [리듀서 함수의 action(실행함수)를 불러오는 것]이다.
7. "action 이 실행"되면, "type(action)마다 정해진, 다른 return 값" 이, "새로운 상태"가 된다.
추가적으로, 대부분의 Reducer 의 State 는 객체 값을 가진다.
import { useReducer } from "react";
function reducerFn(state, action) {
if (action.type == "GET_INFO") {
return { name: "ms", age: 35 }; // "객체값을 갖을 수 있다."
}
if (action.type == "DELETE_INFO") {
return { name: null, age: null };
}
}
function GetUserInfo() {
const [userInfo, dispatch] = useReducer(reducerFn, { name: "", age: null });
function getInfo() {
dispatch({ type: "GET_INFO" });
}
function deleteInfo() {
dispatch({ type: "DELETE_INFO" });
}
console.log(userInfo);
return (
<div>
<button onClick={getInfo}> 얻기 </button>
<button onClick={deleteInfo}> 지우기 </button>
</div>
);
}
export default GetUserInfo;
4. 페이로드 활용하기
페이로드를 활용하면, dispath를 진행하여, action을 가져올때, action 객체에, 프로퍼티 값을 넣을 수 있다.
function userInfoReducer(state, action) {
if (action.type == "GET_INFO") {
return { name: "ms", age: 35, address: action.address }; // "페이로드로, action객체에 값을 넣는다.."
}
if (action.type == "DELETE_INFO") {
return { name: null, age: null };
}
}
function GetUserInfo() {
const [userInfo, dispatch] = useReducer(userInfoReducer, {
name: "",
age: null,
});
function getInfo() {
dispatch({ type: "GET_INFO", address: "busan" }); // 페이로드로 action 객체에 값을 넣는다.
}
...
console.log // { name: "ms", age: 35, address: "busan" }
5. useEffect의 종속성을, state Object 로 사용할때, 문제점과 해결 (destructuring)
state Object를 useEffect 의 종속성에 그대로 넣으면, state 의 모든 프로퍼티가 하나라도 변경 될 때마다 실행 되는
너무나 많이 실행되는 useEffect를 볼 수 있다.
이것은 좋지 않다.
destructuring을 통해, Object 가 아닌, Property 로 종속성을 변경하자
function GetUserInfo() {
const [userInfo, dispatch] = useReducer(userInfoReducer, {
name: "",
age: null,
});
일때,
useEffect(()=>{
...
},[ userInfo ]) // 이렇게 사용하지 않는다.
<개선>
useEffect(()=>{
...
},[ userInfo.name ]) // 프로퍼티를 뽑아 사용한다.
![](https://t1.daumcdn.net/keditor/emoticon/friends1/large/002.gif)
'React > React-Basic' 카테고리의 다른 글
6. className, style 다루기 (0) | 2022.12.12 |
---|---|
5. Context 다뤄보기 - 기본편 (0) | 2022.12.08 |
3. useEffect 바로알기 with. 클린업 프로세스, 디바운싱 (0) | 2022.12.08 |
2. React Portal 사용해보기 (0) | 2022.12.07 |
1. State 끌어올리기(상향식 컴포넌트 데이터 이동) (0) | 2022.12.07 |
댓글