useReducer

sham·2021년 12월 10일
0

Betti 개발일지

목록 보기
9/14

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

useState 말고도 useReducer로 상태를 관리해줄 수가 있다. 컴포넌트에 종속된 useState와는 달리 상태 관련 로직을 컴포넌트에서 분리시킬 수도 있고 컴포넌트 바깥에 작성해 줄수도 있으며 다른 파일에 작성한 후 불러와서 사용하는 것도 가능하다.

리덕스(Redux)의 핵심부분인 reducer를 거의 그대로 구현한다.

소규모 앱에서 useReducer와 컨텍스트 API 조합으로 리덕스를 대체하는 것이 가능하다.

기존의 Hooks는 state마다 setState를 해줘야 했지만 useReducer를 쓰면 한 번의 작업으로 모든 state를 설정해줄 수 있다.

프로토타입

const [state, dispatch] = useReducer(reducer, initalState)

state

state에는 reducer 에서 설정한 state가 들어간다.

클래스처럼 state.{속성}으로 접근할 수 있다.

dispatch

(리덕스에서도 쓰이는) 액션 객체가 들어간다. reducer로 보내줄 값들을 객체 형태로 보내준다.

dispatch({type : 'SET_WINNER', state : '0'}, [])

  • {type : 'SET_WINNER', state : '0'} 객체가 action 객체가 된다.
  • action 객체를 state로 dispatch 할 수 있다.
  • action 객체를 어떻게 처리할지는 reducer에서 처리한다.
  • action을 구분하는 일종의 코드 역할을 하는 문자열은 type으로 설정해주는 것이 일반적.

액션 객체만으로는 state를 바꿀 수 없다. 액션을 해석해서 state를 직접 바꾸는 역할을 하는 것이 reducer이다.

💡 액션의 이름은 상수로 빼는 편이 좋다.

state가 있고, 액션을 dispatch해서 state를 바꾸는데, 그것을 어떻게 바꿀지는 reducer에 써준다.
dispatch만 자식 컴포넌트에서 props로 받아 action을 보내도 reducer가 작동된다.

reducer

현재 상태, 액션 객체를 파라미터로 받아와서 새로운 상태로 반환해주는 함수이다.

const reducer = (state, action) => {
	switch(action.type)
		case 'SET_WINNER' :
			// state.winner = action.winner; 안돼!
			return {
				...state,
				winner: action.winner
}

액션 객체를 구분해서 실제로 실행하는 역할을 한다.

dispatch를 통한 액션 객체가 reducer의 action 인자로 들어온다. state에는 기존의 state가 들어온다.

action 객체의 type을 switch에 집어넣어서 해당되는 case가 있다면 state를 수정한다.

state에 접근해서 직접 바꾸면 안 된다. 객체는 같은 주소를 가리키고 있기에 리액트는 객체 내부의 값이 변했다고 한들 변했다고 생각하지 않고 리렌더링을 하지 않게 된다. 기존 state의 값과 수정된 값을 가진 새로운 객체를 만들어 리턴하는 방식으로 바꿔야만 한다.

initalState

state의 초기값을 설정한다. 클래스의 state와 동일한 모습. 객체형식으로 선언하는 것이 일반적이다.

코드

// TicTacToe.jsx 
import React, {useRef, useState, useReducer, useCallback} from 'react';
import Table from './Table'

const initalState = {
	winner : "",
	turn : "0",
	tableData : [['','',''],['','',''],['','','']],
};

const SET_WINNER = "SET_WINNER";

const reducer = (state, action) => {
	switch(action.type){
		case SET_WINNER :
			return {
				...state,
				winner: action.winner 
		}		
	}
}

const TicTacToe = () => {
	const [state, dispatch] = useReducer(reducer, initalState);
	const onClickTable = useCallback(() => {
	dispatch({type : SET_WINNER, winner : 'O'});
	}, []);

	return (
		<>
		<Table onClick={onClickTable} tableData={state.tableData}/>
		{state.winner && <div>{state.winner}님의 승리</div>}
		</>
	)
}

export default TicTacToe;

전역적으로 state를 관리하고 싶은 곳에 useReducer를 사용. 분할 할당 받은 state로는 state를 관리,dispatch로 action 보내서 state를 변경.
dispatch만 자식 컴포넌트에 props로 보내주어도 reducer 함수에 action이 잘 전달된다.

profile
씨앗 개발자

0개의 댓글