728x90
반응형
복잡한 상태변화 로직을 컴포넌트로부터 외부로 분리하여 컴포넌트를 보다 더 가볍게 작성할 수 있도록 도와줌
useState 대신 사용함
reducer : state 업데이트 하는 역할
dispatch : state 업데이트를 위한 요구
action : 요구의 내용
기본 구조
import { useReducer } from 'react'; function reducer(state, action) { // ... } function MyComponent() { const [state, dispatch] = useReducer(reducer, { age: 42 }); // ...
- 사용 예시
간단한 상태 변경
import React,{useReducer, useState} from 'react';
const reducer = (state, action) => {
console.log('리듀서가 열일중', state, action);
switch(action.type) {
case 'withdraw' : return state - action.payload;
case 'deposit' : return state + action.payload;
default :return state
}
};
export default function Counter() {
const [number, setNumber] = useState(0);
const [money, dispatch] = useReducer(reducer, 0);
return (
<div style={{textAlign:"center", marginTop:'5rem'}}>
<h1>잔고 : {money}원</h1>
<input
type='number'
value={number}
onChange={(e) => setNumber(parseInt(e.target.value))}
step='1000'
/>
<button onClick={() => dispatch({type:'withdraw', payload: number})}>출금</button>
<button onClick={() => dispatch({type:'deposit', payload: number})}>입금</button>
</div>
);
}
보다 더 복잡한 상태변경
import React,{useReducer, useState} from 'react';
import Students from './Students';
const initialState = {
count:1,
students: [{
id : Date.now(),
name : 'James',
isHere : false,
}]
};
const reducer = (state, action) => {
// console.log(state, action.payload);
switch(action.type) {
case 'add' :
const name = action.payload.name;
const newStudents = {
id : Date.now(),
name,
isHere : false,
};
return {
count : state.count+1,
students : [...state.students, newStudents]
}
case 'delete' :
const updatedList = state.students.filter((student) => student.id !== action.payload.id)
return {
count : state.count-1,
students : updatedList,
}
case 'mark' :
return {
count : state.count,
students : state.students.map((student) => {
if(student.id === action.payload.id) {
return {...student, isHere : !student.isHere}
}
return student
})
}
default : return state;
}
};
export default function Counter() {
const [name, setName] = useState('');
const [studentInfo, dispatch] = useReducer(reducer, initialState);
return (
<div style={{textAlign:"center", marginTop:'5rem'}}>
<h1>출석부</h1>
<h2>총 학생수 : {studentInfo.count}</h2>
<input
type='text'
placeholder='이름을 입력해주세요'
value={name}
onChange={(e) => setName(e.target.value)}
/>
<button onClick={()=> {
setName('');
dispatch({ type: 'add', payload: {name} })}
}>추가</button>
{studentInfo.students.map((student) =>
<Students
key={student.id}
name={student.name}
id={student.id}
dispatch={dispatch}
isHere={student.isHere}
/>)}
</div>
);
}
//Students.js
import React from 'react';
export default function Students({name, dispatch, id, isHere}) {
return (
<div>
<span
style={{
textDecoration : isHere ? "line-through" : "none",
color : isHere ? "grey" : "black"
}}
onClick={() => dispatch({
type : 'mark',
payload : {id}
})}>{name}</span>
<button onClick={() =>
dispatch({type:'delete', payload:{id}})}>삭제</button>
</div>
);
}
- 공식문서
https://react.dev/reference/react/useReducer
useReducer – React
The library for web and native user interfaces
react.dev
728x90
'Frontend > React' 카테고리의 다른 글
[React] 프롭 디폴트값 설정 방법 (0) | 2023.04.06 |
---|---|
[React] UseCallback() (0) | 2023.04.04 |
[React] 특정 DOM 선택하기 : UseRef() (0) | 2023.04.02 |
[React][CSS] 테일윈드 (TailWind) 자주쓰는 효과 정리 (0) | 2023.02.24 |
[React] 파이어베이스 (FireBase) 초기 설정 방법 (0) | 2023.02.23 |