강의 유튜브 주소 :

https://www.youtube.com/watch?v=V3QsSrldHqI&list=PLcqDmjxt30RtqbStQqk-eYMK8N-1SYIFn



state나 props가 늘어나면 관리가 힘들어진다.

그리고 props를 넘기게될때 자식에 자식에 자식의 컴포넌트가 있다면 복잡해진다.

이떄 useReducer를 써서 관리할 수 있다.

 

useReducer를 배우면 redux랑 비슷한 효과를 낼 수 있다.

contextAPI + useReducer를 쓸 경우 redux를 사용안해도 되지않나?라고 하는경우들이 있는데

대체하기는 어렵다고 한다.

거창한 redux가 필요없을 경우 (작은 프로젝트)에는 대체하는 형식으로 쓸수는 있다고 한다.

왜냐면 contextAPI와 useReducer를 쓰게되면 비동기 부분을 처리할때 결국 redux를 써야하는 경우가 온다고한다.

즉 흉내라고보면 편하다.

 

useReducer 첫번째인자는 reducer, 두번째인자는 initialState, 세번째는 지연초기화라고 하는데,

지연초기화는 거의안쓰며 가끔 복잡한 경우에 사용한다고한다.

//초기 state선언
const initialState = {    
	winner : '',    
    turn : 'o',        
    tableData : []
}

// 이건 함수, 두개의 인자를 받는다.
const reducer = (state, action) => {    

	// 여기서 state를 어떻게 바꿀지 적는다    
    // 액션이 실행되면 여기서 state를 바꾸어줘야한다.    
    switch(action.type){        
    	case 'SET_WINNER' :             
        	return {                
            	...state,                 
                winner : action.winner 
                
                // dispatch에서 실행되는 액션에 있는 값..            
          }    
    }
}
        
const Test = () => {    
	const [state, dispatch] = useReducer(reduer, initialState);    
        
    // 컴포넌트에 넣는 함수에는 무조건 useCallback    
    const onCLickTable = useCallback(()=>{        
        
       // 액션객체는 {} , dispathch가 실행되면 액션이 실행되었다고 한다        
       dispatch({ type : 'SET_WINNER', winner : 'O' });    
    }, []);    
        
    return(            
       <>                
            
       		// state에서 initialState를 선언했기 떄문에 jsx에서 접근이 가능하다.                
            {state.winner}            
       </>    
    )
};

 

onClick이 발생하면 winner를 o로 변경하는데 이때 dispatch 시킨다.

dispatch안에 들어가는 것은 action이라고 말한다.

action이라는 것은 redux에서 따온 말이라고 한다.

즉 dispatch 함수를 작성한것은 == 액션을 만들었다고 한다.

그리고 실행되면 액션이 실행되었다고 말한다.

 

action만 있다고 자동으로 state가 변경되는 것은 아니다.

action을 읽어서 state로 변경해주는 역할이 필요하다.

그리고 그것이 바로 reducer다.

 

action을 dispatch할때마다 reducer가 실행된다.

 

그리고 state는 initialState로 선언해줬는데, 이 state는 직접 변경하면안된다.

그리고 불변성을 위해 새로운 객체를 늘 넣어줘야한다.

const reducer = (state, action) => {
    switch(action.type){
        case 'SET_WINNER' :
            // 이렇게하면 안됨
            state.winner = action.winner 
    }
}

이렇게 action을 이용해 state를 바뀌는 것을 그림으로 표현해줬다.(출처는!! 제로초님 그림임, 캡쳐해왔습니다.)

그림을 설명해보자면..

일단 state(initialState)가 있고 이벤트가 발생하게되면(click과 같은것들) state를 직접수정하면 안된다.

state를 수정하기 위해서는 action을 만들고 dispatch를 통해 action을 실행한다.

action으로 state를 수정할 수 있다.

action을 어떻게 처리하는가? action의 관리는 reducer가 한다.

 

이때 action의 이름값은 변수로 저장하는 것이 좋다.

강제는 아니지만 action의 이름은 대문자가 좋다. 커뮤니티의 규칙이라고한다.

상수로 선언하고 export를 통해 다른 컴포넌트에서도 사용하는 것이 오류를 줄여준다.

const SET_WINNER = 'SET_WINNER';

const reducer = (state, action) => {
    switch(action.type){
        case SET_WINNER :
         return {
                ...state,
                winner : action.winner // dispatch에서 실행되는 액션에 있는 값..
            }
    }
}

 

action을 만들었으면 자식컴포넌트에서 사용할 수 있도록 export해준다.

// 부모
export const SET_WINNER = 'SET_WINNER';
export const CLICK_CELL = 'CLICK_CELL';

const reducer = (state, action) => {
    switch(action.type){
        case SET_WINNER :
         return {
                ...state,
                winner : action.winner // dispatch에서 실행되는 액션에 있는 값..
            };

    			// 불변성을 지키면서 작업해야한다. 이게 단점. 나중에 immer라는 라이브러리로 가독성 문제를 해결할 수 있다. 유료강좌에서 확인해보아라~~~
        case CLICK_CELL : 
          const data = [...state.data];
          data[data.row] = [...data[data.row]];
                    
          return {
              ...state
          }
    }
}

// 자식
import React, { useCallback } from 'react';
import { CLICK_CELL } from '부모컴포넌트';

const TEST = () => {
    const onClick = useCallback(() => {
        dispatch({
            type : CLICK_CELL, dataIndex : dateIndex
        });
    });

    //...
};

react에서 state를 변경하는 것과 dispatch에서 state를 변경하는 것은 비동기이며 redux는 동기이다.

비동기 state를 처리할 때에는 useEffect를 쓴다.

 

기본적으로 useState로 여러개만들게되면 변수가 많아지고 관리가 어려워진다.

리액트가 redux의 개념으로 state와 dispatch를 관리하기 위해서 useReducer를 도입했다.

initialState에 모든 state를 모아두고 reducer가 action을 통해 setState의 작업을 한다.

 

반복으로 props를 넘겨줘야하는 경우에 contextAPI를 사용한다.

contextAPI는 바로 원하는 컴포넌트로 데이터를 전송할 수 있다.

+ Recent posts