redux 고급

남예지·2023년 8월 31일
0

Redux

목록 보기
3/5
post-thumbnail

좀 더 자세히 Redux에 대해 알아보자.

작업에 페이로드 연결

앞서 포스팅했던 Redux 작동방식까지는 아주 기초적인 액션만 보냈었지만, 실제로 좀 더 복잡한 액션을 보내야하는 일이 많다.
만약 5씩 증가하는 버튼을 만들고 싶다면 +5를 카운터에 더해주는 액션을 하나 더 만드는 식으로는 확장이 불가능하다. 이건 하드코딩일 뿐이니까.
이때는 액션을 통해 추가적인 데이터(페이로드)를 전달해주자.
예를 들어 액션으로부터 증가시키고자 하는 값을 받는 것이다.

리듀서 함수에 아래 코드를 추가해 보자.

const counterReducer = (state = {counter: 0}, action) => {
	if(action.type === "increase") {
    	return{
        	counter: state.counter + action.amount, // 하드 코딩 된 숫자가 아닌 페이로드 속성을 넣어준다.(이름은 마음대로)
        }
    }
    
    return state;
}
export default Counter(){
	const disfatch = useDispatch();
    
    const increaseHandler = () => {
    	disfatch({ type: "increase", amount: 5}) // 5는 하드코딩이지만 input값으로 받을 수도 있다. (어쨌든 확장가능)
    }
	return(
    	<button onClick={increaseHandler}>지정값 증가</button>
    )
}

이렇게 되면 amount의 값을 바꿔주는 것만으로도 유연하게 카운터 state를 다룰 수 있다.

여러가지 state 속성 작업

만약 카운터value가 토글 버튼을 누름으로서 보이거나 보이지 않게 바꿔주는 상태를 만들고싶다면 useState를 사용해 로컬상태에서 관리하는 방법이 있다.
하지만 Counter함수는 컴포넌트 내부에서만 사용되기 때문에 이 안에서 리덕스에 액션을 추가해 만들어보자.

우선 카운터리듀서 함수에 스냅숏을 추가해준다. 이름은 showCounter로 해보자.

const counterReducer = (state = {counter:0, showCounter:true}, action) => {}

그런데 보니까 스냅숏이 늘어날수록 가독성이 안좋아지니 이를 상수에 저장해서 사용하는게 좋겠다.
아래와 같이 바꿔보자.

const initialState = {counter:0, showCounter:true}

const counterReducer = (state = initialState, action) => {}

initialState를 이제서야 이해한 나래기... 개발자 맞으세요? 아뇨 뚱인데요..?

아무튼 기존에 있던 리턴에도 showCounter을 쓰든 안쓰든 넣어줘야 한다. 왜냐면 기존에 state에 합쳐지는게 아니고 리턴되는 값이 기존의 것을 대체하기 때문이다.

그리고 "toggle" 액션도 추가해준다.
아직까지는 스위치 대신 if문을 쓴다고 하는데 나중에 스위치라는 개념이 나오는것인지 아니면 내가 생각하는 그 swich문을 말하는 것인지 모르겠다.

const initialState = {counter:0, showCounter:true}

const counterReducer = (state = initialState, action) => {
	if(action.type === "increase"){
    	return{
        	counter: state.counter + action.amount,
            showCounter: state.showCounter // initialState 기존 값을 출력(아직 필요없음)
        }
    }
    
    if(action.type === "toggle"){
    	return{
        	counter: state.counter
            showCounter: !state.showCounter //전 값과 반대로 설정
        }
    }
}

그리고 Counter 함수 컴포넌트 안에 dispatch해준다.

export default Counter(){
	const disfatch = useDispatch();
    
    const toggleHandler = () => {
    	disfatch({ type: "toggle"})
    }
	return(
    	<button onClick={toggleHandler}>토글 버튼</button>
    )
}

이제 여기서 상태를 가져와 활용하기 위해 useSelector() 커스텀 훅을 사용한다. (저저번 포스팅에 설명있음)

export default Counter(){
	const disfatch = useDispatch();
    const show = useSelector(state => state.showCounter); // 이제 show는 항상 최신상태를 유지하고 상태(데이터)가 변경될 때마다 컴포넌트가 업데이트 된다.
    
    const toggleHandler = () => {
    	disfatch({ type: "toggle"})
    }
	return(
    	<button onClick={toggleHandler}>토글 버튼</button>
    )
}

이런 식으로 여러개의 데이터를 우리 상태에서 관리한다.

리덕스 state의 올바른 사용법

Redux reducer에 리턴되는 객체

기존의 state를 대체하는 스냅숏을 Redux는 항상 반환해야 한다.

왜 항상 새로운 객체로 덮어씌워져서 리턴을 객체로 하게 만들까. 그냥 return state.counter++; 해버리면 안될까.

실행은 될지 몰라도 그렇게 되면 기존의 state를 변경하게 되는 것이다.
redux를 사용할 때에는 기존 state를 덮어씌워야지 변형하는 것은 절대 안된다고 한다. 예측 불가능한 오류나 디버깅이 어려울 수 있다.

리덕스에서 생기는 문제점

애플리케이션의 규모가 커지고 리덕스에서 관리해야 할 상태가 더 많아지면

1 액션타입에서 문제가 생길 수 있다.
액션을 실행할 때 오타가 나면 리듀서가 처리하지 못하거나 오류가 난다. 규모가 커질수록 액션을 관리하기 어려울 수 있다.
2. 관리하는 상태 객체의 크기도 점점 커지고, 리듀서 함수의 길이도 거대해진다. 유지하기 어려울 정도라면 문제가 된다.

물론 자체적으로 상수에 저장하는 등 해결책이 있지만 더 쉬운 방법은 리덕스 툴킷을 사용하는 방법이다.
리덕스 툴킷으로 리덕스를 더 편리하고 쉽게 작동할 수 있다.

다음 포스팅에서 리덕스 툴킷을 사용해보자.

profile
총총

0개의 댓글