본문 바로가기
React

리덕스 관련 알아두면 좋은 내용

by spare8433 2022. 5. 31.

redux-action

액션 생성함수와 리듀서를 작성할때 간단하게 활용하는 라이브러리

 

시작하자마자 모르는 문법이 보여서 체크하고 감

객체 리터럴 표현을 반환하기 위해서는 함수 본문을 괄호 속에 넣음
params => ({foo: bar})

 

createAction() : 액션 생성 함수를 만들어주는 함수이다.
handleActions() : 기존 switch 를 활용한 방법보다 효율적이고 가독성있게 리듀서를 작성할 수 있다.

 

createAction() 을 활용하여 만든 액션 생성 함수는 액션 객체를 던져주는게 아니기 때문에 바로 dispatch 해서 사용이 불가능하고 redux-thunk 같은 액션 생성 함수를 dispatch 할 수 있게 만들어 주어야 편하게 바로 사용이 가능하다.

 

기존 쓰던방식

const INCREASE = 'counter/increase'

//초기값
const initialState = {
    number = 0
}

//액션객체 선언
export const increase = (items) => {
    return {
        type : INCREASE,
        playload:items
    }
}

//리듀서 선언
export function counter (state = initialState, action {
    switch (action.type){
        case INCREASE :
            return{
                number:state.number +1
            }        
        default:
            return state
    }
}

 

redux-actions 활용해 가독성 개선한 코드

https://redux-actions.js.org/

import { createActions, handleActions } from 'redux-actions'

const INCREASE = 'counter/INCREASE'
const DECREASE = 'counter/DECREASE'

//초기값
const initialState = {
    number : 0
}

// 액션 객체 선언
export const increase = createAction(INCREASE,itmes=>({payload:itmes}) )
export const decrease = createAction(DECREASE)

// 리듀서 생성부분
const counter = handleActions(
    {
        [INCREASE]: (state,action) => ({number:state.number +1})
    },
    initialState
)

 

immer

앞선 포스트에서 전개연산자와 함께 불변성의 중요성을 정리하면서 리액트의 특성 때문에 state 를 변경해줄 때 불변성이 더더욱 중요하다 이야기한 바 있다.

 

특정 컴포넌트가 업데이트를 할 필요가 없다는 것을 어떻게 판단할 수 있을까?
가장 간단한 방법은 컴포넌트가 갖고 있는 데이터(props, state)의 이전 이후 값을 완전히 비교하는 것이다. 만약 불변성이 지켜지지 않아 객체 내부의 값이 새로워져도 바뀐 것을 감지하지 못하게 된다.

전개연산자 : https://spare8433.tistory.com/2

 

간단히 말해 원본을 수정하지 않는 선에서 값을 업데이트하여야 한다.

몇몇 내장메서드는 원본데이터를 토대로 새로운 상태를 리턴하는 경우로 처리하면 상관이 없으나 push() 같은 메서드를 활용하면 신경을 더 써야하는 경우가 생긴다.

그래서 간단하게 전개연산자를 활용하는 방식도 있으나 한계가 존재한다.

 

Spread 연산자를 이용한 복사는 얕은(shallow) 복사를 수행하며,
배열 안에 객체가 있는 경우에는 객체 자체는 복사되지 않고 원본 값을 참조합니다.

전개연산자 : https://spare8433.tistory.com/2

 

immer 라이브러리를 활용하면 쉽게 처리가 가능하다.

produce : produce( baseState, (draftState) => void )
첫번째 인자로 세팅할 state 값을 주고
두번째 인자는 첫번째 인자로 들어온 state 형태로 원하는대로 state 를 변경하는 함수를 받아 처리한다. (애초에 원본과 같은 형태의 값을 변경하고 리턴받는 느낌이라 push 같은 원본을 바꿔버리는 메서드를 사용해도 상관이 없다고 한다.)

 

import produce from 'immer'

const [orgininalState, setOrginState] = useState({count:1})

const draftState = produce(orgininalState, draft => {
  draft.count+= 1;
});

console.log(draftState);

 

함수형 업데이트로 사용하는 방법

함수형 업데이트는 state 변경하는 메서드 파라미터state를 받아 처리하는 콜백함수를 받아 최신의 state 값을 사용할 수 있게 하는 방식

추가로 useCallback 함수를 활용하여 함수형 업데이트를 활용하면 처음 실행시만 정의되므로 최적화에 도움이 된다. (일단 useCallback 사용은 계산이 많은 함수에만 사용하는 것을 다들 추천하는 듯 함)

 

immer 라이브러리가 제공하는 produce 메서드와 useState 활용한 업데이트 함수 반환

기존과 방식보다 간편하게 첫 번째 인자를 생략해서 사용 가능하다 (알아서 state 를 인식하는 듯 하다)

 

import {React, useState, useCallback, useEffect} from  'react'
import produce from  'immer'

const Test = () => {

    const [orgininalState, setOrginState] =  useState({count:1})

    const update = useCallback(()=>{
        setOrginState(
            produce(draft  => {
                draft.count  +=  1
            })
        )
    },[])

    // update 함수가 정의될때 실행되는 구문
    useEffect(()=>{ console.log('update 함수는 한번만 정의된다') },[update])

    return (
        <div>
            {orgininalState.count}<br></br>
            <button  onClick={()=>update()}>버튼</button>
        </div>
    )
}
export  default  Test

 

react-actions + immer 합체 진화버젼

 

// 리듀서 생성부분
const counter = handleActions(
    {
        [INCREASE]: (state,action) => 
            produce(state, draft => {
                draft.number = action.payload.number;
    },
    initialState
)

 

사실 redux 를 다룰 때 redux-toolkit 만 쓰면 된다는 것을 듣긴 했지만 한단계 한단계 익히고 넘어가기 위해 정리해두는 것

 

나아아아중에 redux-toolkit 도 정리할 듯

 

'React' 카테고리의 다른 글

React + ts 정적 파일 저장 위치와 기준  (0) 2023.11.06
배열의 index 와 key 의 관계  (0) 2023.02.28
react 에서 inline style 의 단점  (0) 2022.10.12
Hooks  (0) 2022.02.22
ref 를 알아보자 (ref DOM)  (0) 2022.02.21