React

230118 React Hook useReducer()

주영재 2023. 1. 18. 19:50

useReducer()


컴포넌트의 상태 업데이트 로직을 컴포넌트 바깥에 작성할 수도 있고, 
다른 파일에 작성 후 불러와서 사용할 수도 있다.

useState의 사용을 외부에서 사용할 수 있게 해주는 훅(state의 변경을 외부에서 제어할 수 있다.)
+)리덕스 스토어에서 반드시 사용하는 개념임

const myReducer=(현재의 state, action-업데이트에 필요한 정보)=>{
	정보를 판단해서 state를 체인지할 수 있는 구문
    }


const [state-현재값, func-리듀서를 업데이트할 수 있는 함수]=useReducer(외부에서 사용할 리듀서함수, 리듀서의 초기값)


1.리듀서 선언(현재의 state, 업데이트에 필요한 정보)

-console.log(state);를 하면 useReducer에서 준 리듀서의 초기값이 나온다. 

-이 리듀서에서 state를 변경해 주는 구문을 넣는다.

-useReduce에서 action으로 넘어온 것을 통해 업데이트하는 구문을 만드는 것.

 

2.useReducer(선언한 리듀서, 리듀서의 초기값)

-리듀서의 초기값은 객체다.

-useReducer는 구조분해할당으로 [state,func]를 받을 수 있다. 처음 console.log(state);를 하면 리듀서의 초기값이 나온다.
-func함수가 선언한 리듀서를 대신 실행한다. 

-func함수의 매개변수로 원하는 걸 넣으면 선언한 리듀서의 action에서 사용할 수 있다.

 

"1과 2를 번갈아 읽으며 이해해야 한다."

 


=>useState처럼 state를 바꾸는데, useReducer는 바깥이나 다른 파일에서 관리할 수 있다는 차이가 있음.


HookReducer

import { useEffect, useReducer } from "react";
import {myReducer} from './../hook/HookReducerComponent'

//리듀서 선언(현재의 state, 업데이트에 필요한 정보)
//action을 판단해서 state를 체인지
/*
const myReducer = (state, action)=>{
    //action은 객체
    // console.log(state); //리듀서의 초기값
    // console.log(action); //업데이트에 필요한 정보

    if(action.type==='increase'){
        state={value:state.value+1}
    }else if(action.type==='decrease'){
        state={value:state.value-1}
    }else if(action.type==='reset'){
        state={value:0}

    }

    return state;
}
*/


const HookReducer=()=>{
    //const [현재값, 리듀서를 업데이트할 수 있는 함수]=useReducer(외부에서 사용할 리듀서함수, 리듀서의 초기값)
    const [state,func]=useReducer(myReducer,{value:0});
    const up =()=>{
        func({type:'increase'})
    }
    
    // useEffect(()=>{
    //     func({type:'reset'}); //리듀서를 실행시키고, myReducer에 action으로 전달됩니다.
    // },[])
    // console.log(state);

    return(
        <>  
        <button onClick={up}>증가</button>
        <button onClick={()=>func({type:'decrease'})}>감소</button>
        <button onClick={()=>func({type:'reset'})}>초기화</button>
        결과: {state.value}
        </>
    )
}

export default HookReducer;

HookReducer2

import { useReducer } from "react";
import { nameReducer } from "./HookReducerComponent";

//리듀서
/*
const nameReducer = (state, action) => {
    //console.log(action); //e.target

    state={...state,[action.name]:action.value}

    return state;
}
*/




const HookReducer2 = () => {
    //[스테이트,리듀서제어함수]=useReducer(리듀서,초기값)
    const [state, func] = useReducer(nameReducer, { name: '', age: '' })

    const { name, age } = state; //스테이트 값 구조분해할당

    return (
        <>
            이름: <input type="text" name="name" onChange={(e)=>func(e.target)}/>
            나이: <input type='text' name='age' onChange={(e)=>func(e.target)}/>
            <br />
            결과값: {name}<br />
            결과값: {age}<br />

        </>
    )
}

export default HookReducer2;

구조분해할당을 한 건 아래 return문에서 사용하기 위해서임.


HookReducerComponent

const myReducer = (state, action)=>{
    //action은 객체
    // console.log(state); //리듀서의 초기값
    // console.log(action); //업데이트에 필요한 정보
    if(action.type==='increase'){
        state={value:state.value+1}
    }else if(action.type==='decrease'){
        state={value:state.value-1}
    }else if(action.type==='reset'){
        state={value:0}

    }

    return state;
}

const nameReducer = (state, action) => {
    //console.log(action); //e.target

    state={...state,[action.name]:action.value}

    return state;
}

//기본디폴트 모형. export default는 하나밖에 반환 못함. 
//이 방식으로 하면 객체를 반환하고. 그 객체 안에는 함수만 있는 것.
export {myReducer, nameReducer};

첫번째 리듀서는 func에서 객체를 받았기에 action.type을,

두번째 리듀서는 func에서 e.target을 받았기에 action.name이나 action.value를 사용.

 

->같은 js파일에서 컴포넌트 밖에서 리듀서를 만들 수도 있고, 다른 파일에서 리듀서를 만들고 export, import 할 수도 있다.

->state를 외부에서 관리할 수 있다는 장점이 있다. 마찬가지로 화면은 리렌더링된다.

 

 

증가,감소,초기화,input태그에 입력하는 것 모두 리렌더링됨.