useReducer
사용자 리스트 기능에서의 주요 상태 업데이트 및 컴포넌트의 상태 업데이트 로직을 컴포넌트에서 분리시킬 수 있습니다.
컴포넌트에서 관리하는 값이 여러개가 되어 상태의 구조가 복잡하다면 useReducer 사용, 컴포넌트에서 관리하는 값이 하나고 단순한 숫자 또는 문자열이라면 useSate로 관리
reducer 기본 문법
reducer 에서 반환하는 상태는 곧 컴포넌트가 지닐 새로운 상태가 되며, action은 업데이트를 위한 정보를 가지고 있습니다.
type 값을 지닌 객체 형태로 사용하지만, 꼭 따라야 할 규칙은 없음
// 현재 상태와 액션 객체를 파라미터로 받아서 새로운 상태를 반환해주는 함수
function reducer(state, action) {
// 새로운 상태를 만드는 로직
// const nextState = ...
return nextState;
}
useReducer 기본 문법
//state는 우리가 앞으로 컴포넌트에서 사용할 수 있는 상태를 가르킴
//dispatch 는 액션을 발생시키는 함수
//reducer === reducer의 이름의 함수
//dispatch === 초기 상태
const [state, dispatch] = useReducer(reducer, initialSatate);
Counter.js
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(
<React.Fragment>
<h1>{number}</h1>
<button onClick={onIncrease} type="button">+1</button>
<button onClick={onDecrease} type="button">-1</button>
</React.Fragment>
)
}
export default Counter;
App.js
import React, {useRef, useReducer, useMemo, useCallback} from 'react';
import Inner from "./Inner";
import UserList from "./UserList";
import CreateUser from "./CreateUser";
function countActiveUsers(users) {
console.log('활성 사용자 수를 세는중')
return users.filter(user => user.active).length;
}
const initialState = {
inputs: {
username: '',
email: ''
},
users: [
{
id: 1,
username: 'a',
email: 'a@aaa.com',
active: true
},
{
id: 2,
username: 'b',
email: 'b@bbb.com',
active: false
},
{
id: 3,
username: 'c',
email: 'c@ccc.com',
active: false
}
]
};
function reducer(state, action) {
switch (action.type) {
case 'CHANGE_INPUT' :
return {
...state,
inputs: {
...state.inputs,
[action.name] : action.value
}
};
case 'CREATE_USER':
return {
inputs: initialState.inputs,
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:
return state;
}
}
function App() {
const [state, dispatch] = useReducer(reducer, initialState);
const nextId = useRef(4);
const {users} = state;
const {username, email} = state.inputs;
const onChange = useCallback(e => {
const { name, value } = e.target;
dispatch({
type: 'CHANGE_INPUT',
name,
value
});
}, []);
const onCreate = useCallback(() => {
dispatch({
type: 'CREATE_USER',
user: {
id: nextId.current,
username,
email
}
});
nextId.current += 1;
}, [username, email]);
const onToggle = useCallback(id=> {
dispatch({
type : 'TOGGLE_USER',
id
});
}, []);
const onRemove = useCallback(id=> {
dispatch({
type: 'REMOVE_USER',
id
}) ;
}, []);
const count = useMemo(() => countActiveUsers(users), [users]);
return (
<React.Fragment>
<Inner>
<CreateUser username={username} email={email} onChange={onChange} onCreate={onCreate}/>
<UserList users={users} onToggle={onToggle} onRemove={onRemove}/>
<p>활성사용자 수 : {count}</p>
</Inner>
</React.Fragment>
);
}
export default App;
'Web Tech > react' 카테고리의 다른 글
react 기본 - 18.Context API 로 전역 값 관리 (0) | 2021.12.06 |
---|---|
react 기본 - 17.커스텀 Hooks (0) | 2021.12.06 |
react 기본 - 15.React.memo (0) | 2021.11.30 |
react 기본 - 14.useCallback (0) | 2021.11.30 |
react 기본 - 13.useMemo (0) | 2021.11.23 |