230118 React Hook useReducer()
useReducer()
컴포넌트의 상태 업데이트 로직을 컴포넌트 바깥에 작성할 수도 있고,
다른 파일에 작성 후 불러와서 사용할 수도 있다.
useState의 사용을 외부에서 사용할 수 있게 해주는 훅(state의 변경을 외부에서 제어할 수 있다.)
+)리덕스 스토어에서 반드시 사용하는 개념임
const myReducer=(현재의 state, action-업데이트에 필요한 정보)=>{
정보를 판단해서 state를 체인지할 수 있는 구문
}
const [state-현재값, func-리듀서를 업데이트할 수 있는 함수]=useReducer(외부에서 사용할 리듀서함수, 리듀서의 초기값)
1.리듀서 선언(현재의 state, 업데이트에 필요한 정보)
-console.log(state);를 하면 useReducer에서 준 리듀서의 초기값이 나온다.
-이 리듀서에서 state를 변경해 주는 구문을 넣는다.
-useReduce에서 action으로 넘어온 것을 통해 업데이트하는 구문을 만드는 것.
2.useReducer(선언한 리듀서, 리듀서의 초기값)
-리듀서의 초기값은 객체다.
-useReducer는 구조분해할당으로 [state,func]를 받을 수 있다. 처음 console.log(state);를 하면 리듀서의 초기값이 나온다.
-func함수가 선언한 리듀서를 대신 실행한다.
-func함수의 매개변수로 원하는 걸 넣으면 선언한 리듀서의 action에서 사용할 수 있다.
"1과 2를 번갈아 읽으며 이해해야 한다."
=>useState처럼 state를 바꾸는데, useReducer는 바깥이나 다른 파일에서 관리할 수 있다는 차이가 있음.
HookReducer
import { useEffect, useReducer } from "react";
import {myReducer} from './../hook/HookReducerComponent'
//리듀서 선언(현재의 state, 업데이트에 필요한 정보)
//action을 판단해서 state를 체인지
/*
const myReducer = (state, action)=>{
//action은 객체
// console.log(state); //리듀서의 초기값
// console.log(action); //업데이트에 필요한 정보
if(action.type==='increase'){
state={value:state.value+1}
}else if(action.type==='decrease'){
state={value:state.value-1}
}else if(action.type==='reset'){
state={value:0}
}
return state;
}
*/
const HookReducer=()=>{
//const [현재값, 리듀서를 업데이트할 수 있는 함수]=useReducer(외부에서 사용할 리듀서함수, 리듀서의 초기값)
const [state,func]=useReducer(myReducer,{value:0});
const up =()=>{
func({type:'increase'})
}
// useEffect(()=>{
// func({type:'reset'}); //리듀서를 실행시키고, myReducer에 action으로 전달됩니다.
// },[])
// console.log(state);
return(
<>
<button onClick={up}>증가</button>
<button onClick={()=>func({type:'decrease'})}>감소</button>
<button onClick={()=>func({type:'reset'})}>초기화</button>
결과: {state.value}
</>
)
}
export default HookReducer;
HookReducer2
import { useReducer } from "react";
import { nameReducer } from "./HookReducerComponent";
//리듀서
/*
const nameReducer = (state, action) => {
//console.log(action); //e.target
state={...state,[action.name]:action.value}
return state;
}
*/
const HookReducer2 = () => {
//[스테이트,리듀서제어함수]=useReducer(리듀서,초기값)
const [state, func] = useReducer(nameReducer, { name: '', age: '' })
const { name, age } = state; //스테이트 값 구조분해할당
return (
<>
이름: <input type="text" name="name" onChange={(e)=>func(e.target)}/>
나이: <input type='text' name='age' onChange={(e)=>func(e.target)}/>
<br />
결과값: {name}<br />
결과값: {age}<br />
</>
)
}
export default HookReducer2;
구조분해할당을 한 건 아래 return문에서 사용하기 위해서임.
HookReducerComponent
const myReducer = (state, action)=>{
//action은 객체
// console.log(state); //리듀서의 초기값
// console.log(action); //업데이트에 필요한 정보
if(action.type==='increase'){
state={value:state.value+1}
}else if(action.type==='decrease'){
state={value:state.value-1}
}else if(action.type==='reset'){
state={value:0}
}
return state;
}
const nameReducer = (state, action) => {
//console.log(action); //e.target
state={...state,[action.name]:action.value}
return state;
}
//기본디폴트 모형. export default는 하나밖에 반환 못함.
//이 방식으로 하면 객체를 반환하고. 그 객체 안에는 함수만 있는 것.
export {myReducer, nameReducer};
첫번째 리듀서는 func에서 객체를 받았기에 action.type을,
두번째 리듀서는 func에서 e.target을 받았기에 action.name이나 action.value를 사용.
->같은 js파일에서 컴포넌트 밖에서 리듀서를 만들 수도 있고, 다른 파일에서 리듀서를 만들고 export, import 할 수도 있다.
->state를 외부에서 관리할 수 있다는 장점이 있다. 마찬가지로 화면은 리렌더링된다.