useState의 대체 함수.
(state, action) => newState의 형태.
reducer를 받고 dispatch의 메서드와 짝의 형태로 현재 state를 반환.
const [state, dispatch] = useReducer(reducer, initialArg, init);
useReducer사용하여 active 사용자 count하기
import React, {useReducer} from 'react'
const Counter = () => {
function reducer(state, action){
switch(action.type){
case 'INCREMENT':
return state+1;
case "DECREMENT":
return state-1;
default :
return state;
}
}
const [number, dispatch] = useReducer(reducer, 0);
const increase = () => {
dispatch({type : "INCREMENT"})
}
const decrease = () => {
dispatch({type : "DECREMENT"})
}
return (
<div>
<h1>{number}</h1>
<button onClick={increase}>+1</button>
<button onClick={decrease}>-1</button>
</div>
)
}
export default Counter
반복되는 로직을 쉽게 재사용 하기 위해 직접 만들어 사용하는 hook
보통 파일 이름은 Use-로 시작
user를 새로 input하는 custom hook을 만들어 보자
import {useState, useCallback} from 'react'
const UseInputs = (initialForm) => {
const [form, setForm] = useState(initialForm);
const onChange = useCallback((e)=> {
const {name, value} = e.target;
setForm(form => ({...form, [name]:value}))
}, [])
const reset = useCallback(()=>setForm(initialForm), [initialForm]);
//form을 초기화
return (
[form, onChange, reset]
)
}
export default UseInputs
import React, { useReducer, useCallback, useRef, useMemo } from 'react'
import UserList from './components/UserList'
import CreateUser from './components/CreateUser'
import UseInputs from './components/UseInputs'
const initialState = {
users : [
{
id : 1,
username : 'jisung',
email : 'jisung@gmail.com',
Active : true
},
{
id : 2,
username : 'mark',
email : 'marklee@naver.com',
Active : false
},
{
id : 3,
username : 'jeongwoo',
email : 'jeongwoo@gmail.com',
Active : false
}
]
}
function reducer(state, action){
switch(action.type){
case "CREATE_USER":
return{
users : state.users.concat(action.user)
}
case "TOGGLE_USER":
return{
...state,users:state.users.map(user=>
user.id === action.id ? {...user,active : !user.active}:user)
}
case "REMOVE_USER":
return {
...state, users:state.users.filter(user=>user.id !== action.id)
}
default:
throw new Error("액션 없음!");
}
}
function countActiveUsers(users){
return users.filter(user => user.active).length;
}
function App() {
const [state, dispatch] = useReducer(reducer, initialState);
const {users} = state;
const nextId = useRef(4);
const [form, onChange, reset] = UseInputs({
username : "",
email : ""
});
const {username, email} = form;
const onToggle = useCallback((id)=>{
dispatch({
type : "TOGGLE_USER",
id
})
}, [])
const onRemove = useCallback((id)=>{
dispatch({
type : "REMOVE_USER",
id
})
}, [])
const onCreate = useCallback(()=>{
dispatch({
type : "CREATE_USER",
user : {
id : nextId.current,
username,
email
}
})
reset();
nextId.current+=1;
}, [username,email,reset])
const count = useMemo(()=>countActiveUsers(users), [users])
return (
<>
<CreateUser
username={username}
email={email}
onChange={onChange}
onCreate={onCreate}
/><br/>
<UserList users={users} onToggle={onToggle} onRemove={onRemove}/><br />
<div>Active 상태의 사용자 수 : {count} </div>
</>
);
}
export default App;
출처 :
useReducer
커스텀 hooks 만들기