다음으로 useReducer에 대해 배워보자. useState와 비슷하게
현재 상태, 그리고 상태의 업데이트에 필요한 정보를 담은 action 값을 전달 받아 새로운 상태값을
return해주는 함수이다.
사용 방법도 비슷한데, useReducer는 상태를 바꿔주는 코드를 한 블럭에 몰아 넣고 이를 컴포넌트 밖으로
빼낼 수 있다는 것이 장점이다.
src 폴더에 useReduce 폴더를 만들고 Reduce.jsx 파일을 만든다.
/* src/useReduce/Reduce.jsx */
import react, { useReducer } from 'react'
const Reduce = () => {
return(
<>
<h2> How to use Reducer </h2>
<p>
<button> show userid </button>
<button> show userpw </button>
<button> add list </button>
</p>
--------------------------------------
<div>
<li>
userid :
</li>
<li>
userpw :
</li>
</div>
--------------------------------------
<div></div>
</>
)
}
return default Reduce
우리는 버튼을 클릭하면 아래의 list에서 대응하는 값이 나타나도록 하고 싶다.
이런 state의 변화를 useReducer를 사용해 구현할 것이다.
Reduce 함수 안에 다음과 같이 useReducer 훅을 추가해주자.
/* src/useReduce/Reduce.jsx */
const Reduce = () => {
const [state, dispatch] = useReducer(reducer, initalstate)
...후략
}
괄호안의 인자들은 예전에 useState를 사용했을때 사용한 인자들과 거의 동일한 기능을 한다.
우리는 처음에 dispatch의 값을 바꿔 useReducer를 거쳐 reducer 함수 (좀 이따 만들거)
최종적으로 state를 바꿔준다.
useReducer의 첫 번째 인자는 우리가 state의 변화를 디자인하는 함수, 두 번째 인자는 초기 상태를 의미한다.
첫 번째 인자(함수)는 우리가 원하는대로 만들어주면 된다.
그런데 이 initialState, reducer함수는 컴포넌트 밖에, 심지어 다른 파일에도 나눠서 작성할 수 있다.
여기서는 같은 파일에 작성하되, 컴포넌트 외부에 작성한다.
/* src/useReduce/Reduce.jsx */
const initialState = {
user: {
userid:'userid',
userpw:'userpw'
},
board: [
{ idx : 0, subject: 'qwerty', content: 'asdfgh', date : '2022-04-28' }
]
}
초기상태를 포함한 state의 data type은 굳이 객체가 아니라도 상관없다.
이제 reducer 함수를 작성한다.
/* src/useReduce/Reduce.jsx */
const reducer = (state, action) => {
switch(action.type) {
case 'SHOW_ID' :
return {
...state,
user: {
...state.user,
userid:'qwerty123'
}
}
case 'SHOW_PW' :
return {
...state,
user: {
...state.user,
userpw:'asdfg456'
}
}
case 'SHOW_LIST' :
return {
...state,
board : [
...state.board,
{subject: 'qwerty2', content:'asdfgh2', date:'2022-04-28'}
]
}
}
return state
}
reducer 함수는 state와 action을 매개변수로 받는다. state는 원래 상태이고, 우리가 조정해줄 것은 action이다.
함수를 보면 알 수 있듯 action의 값을 읽고 그 action에 대응하는 코드를 실행해
그 코드블럭 안의 내용을 기반으로 state값을 바꾼 후 return해준다.
이제 이 action 값들을 가져갈 함수, 그 함수를 가져갈 element들을 정해주면 된다.
Reduce 함수 컴포넌트 안에 다음과 같이 함수를 설정한다.
/* src/useReduce/Reduce.jsx */
const Reduce = () => {
const [state, dispatch] = useReducer(reducer, initialState)
const handleClick = () => {
dispatch({type:'SHOW_ID'})
}
const handleClick2 = () => {
dispatch({type:'SHOW_PW'})
}
const showList = () => {
dispatch({type:'SHOW_LIST'})
}
const items = () => state.board.map((v) => {
return (
<ul key={v.idx}>
<li>{v.subject}</li>
<li>{v.content}</li>
<li>{v.date}</li>
</ul>
)
})
return(
<>
<h2> How to use Reducer </h2>
<p>
<button onClick = {handleClick}> show userid </button>
<button onClick = {handleClick2}> show userid </button>
<button onClick = {showList}> show userid </button>
</p>
--------------------------------
<div>
<li>
userid: { state.user.userid }
</li>
<li>
userpw : { state.user.userpw }
</li>
</div>
--------------------------------
<div>{items()}</div>
</>
)
}
show userid 버튼을 누르면 handleClick 함수가 실행된다.
handleClick 함수는 disptach를 실행하는데, 이 안에 reducer 함수에 전해줄 action type이 있다.
handleClick 함수는 action.type = 'CHANGE_ID' 을 reducer 함수에 전달해
switch문에서 해당하는 action.type을 가진 조건문이 실행된다.
따라서 원래 state를 복사해 가져온 후, userid를 바꾼 후 return한다.
마지막으로 reducer 함수를 다른 파일로 분리해보자.
동일한 폴더에 reducer.jsx 폴더를 만들고 reducer 함수를 옮긴다.
/* src/useReduce/reducer.jsx */
const reducer (state, action) => {
switch (action.type) {
case 'CHANGE_ID' :
return {
...state,
user: {
...state.user,
userid:'qwerty123'
}
}
case 'CHANGE_PW' :
return {
...state,
user: {
...state.user,
userpw:'asdfg456'
}
}
case 'ADD_LIST' :
return {
...state,
board: [
...state.board,
{idx:1, subject: 'qwerty2', content: 'asdfgh2', date:'2022-04-28'}
]
}
}
return state
}
export default reducer
이걸 다시 Reduce.jsx로 import하면 된다.
/* src/useReduce/Reduce.jsx */
import react, {useReducer} from 'react'
import reducer from './reducer.jsx'
const initialState = {
user: {
userid:'userid',
userpw:'userpw'
},
board: [
{idx:0, subject: 'qwerty', content: 'asdfgh', date:'2022-04-28'}
]
}
const Reduce = () => {
const [state, dispatch] = useReducer(reducer, initialState)
const handleClick = () => {
dispatch({type: 'CHANGE_ID'})
}
const handleClick2 = () => {
dispatch({type: 'CHANGE_PW'})
}
const addList = () => {
dispatch({type:'ADD_LIST'})
}
const items = () => state.board.map((v) => {
return(
<ul key={v.idx}>
<li>{v.subject}</li>
<li>{v.content}</li>
<li>{v.date}</li>
</ul>
)
})
return (
<>
<h2> How to use Reducer </h2>
<p>
<button onClick = {handleClick}> show userid </button>
<button onClick = {handleClick2}> show userpw </button>
<button onClick = {addList}> add list </button>
</p>
---------------------------------------
<div>
<ul>
<li>
userid : {state.user.userid}
</li>
<li>
userpw : {state.user.userpw}
</li>
</ul>
</div>
---------------------------------------
<div>{items()}</div>
</>
)
}
export default Reduce
'React' 카테고리의 다른 글
#15 Redux part1 (0) | 2022.05.07 |
---|---|
#14 useMemo, useCallback (0) | 2022.05.02 |
#12 useContext (0) | 2022.04.29 |
#11 함수형 컴포넌트 2. useEffect (0) | 2022.04.29 |
#10 함수형 컴포넌트 1. intro, useState (0) | 2022.04.29 |