본문 바로가기
Frontend/React

[React] useReducer()

by 민두이 2023. 4. 5.
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

 

https://react.vlpt.us/basic/20-useReducer.htm

728x90