현재상태(state), 업데이트를 위해 필요한 정보가 있는 action 을 받아 새로운 상태로 반환하는 함수
반드시 불변성을 지켜야 한다. (State과 같이 원본의 불변을 유지해야 한다.)
import React, { useReducer } from "react"
function reducer(state, action) {
switch (action.type) {
case "INCREMENT":
return { value: state.value + 1 }
case "DECREMENT":
return { value: state.value - 1 }
default:
return state
}
}
const Counter = () => {
const [state, dispatch] = useReducer(reducer, { value: 0 })
return (
<div>
<p>
현재 카운터 값은 <b>{state.value}</b>
</p>
<button
onClick={() => {
dispatch({ type: "INCREMENT" })
}}
>
+1
</button>
<button
onClick={() => {
dispatch({ type: "DECREMENT" })
}}
>
-1
</button>
</div>
)
}
export default Counter
const [현재 가리키고 있는 상태, 액션발생함수 ] = useReducer(reducer,해당 리듀서의 기본값)
함수 안에 파라미터로 액션값 ({type : 'INCREMENT'})
을 넣어주면 리듀서가 호출되는 구조
그래서..뭐가 좋은거냐 ?
1. 컴포넌트 업데이트 로직을 컴포넌트 바깥으로 뺄 수 있다.
2. type이 무엇인지에 따라서 다양하게 값을 처리할 수 있다.
또다른 예제,
import React, { useReducer } from "react"
function reducer(state, action) {
return {
...state,
[action.name]: action.value,
}
}
export default function Info() {
const [state, dispatch] = useReducer(reducer, { name: "", nickname: "" })
const { name, nickname } = state
const onChange = (e) => {
dispatch(e.target)
}
return (
<div>
<div>
<input name="name" value={name} onChange={onChange} />
<input name="nickname" value={nickname} onChange={onChange} />
</div>
<div>
<div>
<b>이름</b> : {name}
</div>
<div>
<b>닉네임</b> : {nickname}
</div>
</div>
</div>
)
}
action은 어떠한 값도 사용이 가능하다. 여기서는 e.target (dispatch(e.target)
) 을 넘겨줌