본문 바로가기

React/React 심화

React 심화 기능 )) useReducer

1. 상태 변화 코드란?

- 상태 변화 코드 : State값을 변경하는 코드

- 상태 변화 코드를 컴포넌트에서 분리한다 : 컴포넌트 내부에 작성했던 상태 변화 코드를 외부에 작성한다는 뜻

- useState를 이용해 State를 만들면 상태 변화 코드를 분리 할 수 없다. 둘 다 컴포넌트 안에서 선언하기 때문이다.

- 하나의 컴포넌트 안에 너무 많은 상태 변화 코드가 있는 경우 가독성을 해쳐 유지 보수를 어렵게 만든다.

2. useReducer의 기본 사용법

- useReducer : useState와 더불어 State를 관리하는 리액트 훅(useState의 대체제라고 할 수 있다.)

-useState 와 use Reducer의 차이점

  useState useReducer
State 관리 컴포넌트 내부 컴포넌트 외부(파일로도 분리가 가능하다.)
사용 시기 State가 단순할 때 State가 복잡할 때
사용법 const [ state, setState ] = useState(초깃값) const [ state, dispatch ] = useReducer(reducer, action)

 

- state : state 변수
- dispatch : 상태 변화 촉발 함수(상태 변화가 필요할 때 이를 촉발하는 함수 dispatch를 호출한다. 인수로 전달하는 객체는 State의 변경 정보를 담고 있다.)
- useReducer( ) : 생성자
- reducer : 상태 변화 함수
- action : dicpatch 함수에서 인수로 전달되는 객체
예시 1))

import { useReducer } from "react";

function reducer () {     //reducer 함수를 컴포넌트 밖에 만든다.실질적인 상태변화는 reducer 함수안에서 발생한다!
	switch(action.type){
    	case "INCREASE":
        	return state+action.data;
        case "DECREASE":
        	return state-action.data;
        case "INIT":
        	return 0;
        dafault:
        	return state;
    }
}

function TestComp() {
	const [count, dispatch] = useReducer(reducer, 0);    //useReducer의 첫번째 인자로 reducer 함수를 지정

	return (
    	<div>
        	<h4>테스트 컴포넌트</h4>
            <div>
            	<bold>{count}</bold>
            </div>
            <div>    //button을 클릭했을 때 dispatch함수를 리턴하는 함수를 설정. 인수로 객체를 전달한다.)
            	<button onClick={() => {dispatch({type: "INCREASE", data: 1})}}>
                +                     //type은 어떤 상황이 발생했는지 나타냄. data는 상태 변화에 필요한 값
                </button>
                <button onClick={() => {dispatch({type: "DECREASE", data: 1})}}>
                -
                <button>
                <button onClick={() => {dispatch({type: "INIT"})}}>
                0으로 초기화
                <button>
            </div>
        </div>
    )
}

export default TestComp;
예시 2))

import { useReducer, useRef } from "react";

function reducer(state, action){    //상태 변화 로직
	switch(action.type){
    	case "CREATE": {
        	return [action.newItem, ...state];
        }
        case "UPDATE": {
        	return state.map((it) =>
            	it.id === action.targetId
                	? {
                    	...it,
                        isDone: !it.isDone,
                        }
                    : it
            );
        }
        case "DELETE": {
        	return state.filter((it) => it.id !==action.targetId);
        }
        default:
        	return state;
    }
}

function App(){
	const [todo, dispatch] = useReducer(reducer, mockTodo);
    const idRef = useRef(3);
    
    const onCreate = (content) => {    //할 일 추가 이벤트
    	dispatch{
        	type: "CREATE",
            newItem: {
            	id: idRef.current,
                content,
                isDone: false,
                createdDate: newDate().getTime(),
            },
        };
    	idRef.current += 1;
    };
    const onUpdate = (targetId) => {     //할 일 수정 이벤트
    	dispatch({       //체크 여부로 수정할 아이템의 id를 설정한다.
        	type: "UPDATE",
            targetId,
            });
        
    };
    const onDelete = (targetId) => {
    	dispatch({
        	type: "DELETE",
            targetID,
        });
    };
    
}

export default App;
728x90