React.js

21.04.02 useReducer

슈팅스타제제 2021. 4. 10. 15:41

입력한 데이터를 화면에 바로 렌더링해보자.

📌useReducer

useState보다 다양한 컴포넌트 상황에 따라 다른 값으로 업데이트해주고 싶을 때 사용한다. 

reducer 함수는 현재 상태, 업데이트를 위해 필요한 정보를 담은 값 (action)을 전달받아 새로운 상태를 반환하는 함수이다. 리듀서 함수에서 새로운 상태를 만들 때는 반드시 불변성을 지켜줘야 한다. 

리덕스에서 사용하는 액션 객체에는 아래와 같이 반드시 어떤 액션인지 알려주는 type field가 꼭 있어야 하지만

{

 type : '뭐시기', 

useReducer 에서 사용하는 액션 객체는 꼭 type을 지니고 있을 필요는 없다. 

그리고 굳이 객체가 아니라 문자열이나 숫자여도 상관없다. 

 

✔ Counter.js

useReducer를 사용했을 때 컴포넌트 업데이트 로직을 바깥으로 빼낼 수 있는 것이 장점인데 

아래와 같이 컴포넌트 바깥에서 useReducer의 인자인 리듀서 함수를 정의한다. 

import React {useState, useReducer} from 'react';

function reducer(state, action){
	switch(action.type){
    	case 'INCREMENT':
        	return { value : state.value + 1 };
        case 'DECREMENT':
        	return {value : state.value - 1 };
        default:
        	return state; //아무것도 없으면 기초 상태를 반환!
    }
}

dispatch(aciton) : 함수 안에 파라미터로 액션 값을 넣으면 리듀서 함수가 호출되며 그 데이터가 넘어간다. 

const Counter = () => {
    //state : 현재 상태 
    //dispatch : 액션을 발생시키는 함수 
    //reducer : 리듀서 함수
    //{value : 0} : 해당 리듀서 기본 상태
    const [state, dispatch] = useReducer(reducer, {value : 0}); 
    
    return (
    	<div>
        	<p>현재 카운터 값은 <b>{state.value}</b>입니다.</p>
            <button onClick = {()=>dispatch({type : 'INCREMENT'})}>+1</button>
            <button onClick = {()=>dispatch({type : 'DECREMENT'})}>-1</button>
        </div>
    );
 };
 
 export default Counter;

 

✔ Info.js

리듀서 함수 정의해준다.  

불변성을 유지하기 위해 원본 배열을 건드리지 않는 spread 연산자를 사용하여 상태를 반환한다. 

import React, {useReducer} from 'react';

function reducer(state, action){
	return {
    	...state, 
        [action.name] : action.value, 
    };
};

이름과 별명의 초기값을 설정하고 입력값이 바뀔 때 이벤트를 정의한 후 

인풋 태그에서 받은 값에 따라 아래 이름과 별명을 값을 즉각적으로 렌더링한다. 

const Info = ()=>{
	const [state, dispatch] = useReducer(reducer, {
    	name : '', 
        nickname : '', 
    });
    const {name, nickname} = state;
    const onChange = (e)=>{
    	dispatch(e.target);
    };
    return (
    	<div>
        	<div>
            	<input name = "name" value = {name} onChange = {onChange} />
                <input name = "nickname" value = {nickname} onChange = {onChange} />
            </div>
            <div>
            	<b>이름 : </b>
                {name}
            </div>
            <div>
            	<b>별명 : </b>
                {nickname}
            </div>
        </div>
     );
 };
 
 export default Info;