Redux 사용방법(Basic)

양정규·2025년 2월 21일
0
post-thumbnail

핵심 주제


  • redux의 사용흐름
  • useRef Hook 간단히 알아보기
  • redux 코드 개선하기

학습 내용 정리


redux의 사용흐름

  1. reducer(리듀서)를 생성하고, createStore 메소드를 이용해서 리듀서를 스토어에 연결합니다.

    // reducer.js
    export default function reducer(state, action) {
      if (state === undefined) { //초기값을 주려고 undefined설정
        return {
          user: null, 
          languages: [
            {
              name: "JavaScript",
              keyword: "Web Frontend",
            },
          ],
        };
      }
      
      // main.jsx
      import { legacy_createStore as createStore } from "redux";
      import reducer from "./reducer.js";
      
      const store = createStore(reducer); 
  2. 사용하기 위한 컴포넌트의 상위 컴포넌트를 provider 컴포넌트로 감싸주고 store 속성에 생성해둔 스토어를 연결합니다.

      // main.jsx
      import { Provider } from "react-redux";
      
      <Provider store={store}>
        <App />
      </Provider>
  3. 필요한 상태를 가져오기 위해서는 useSelector를 사용해서 가져온다.

    • (state) => state처럼 상태를 다 가져오는 것은 명시적이지 않기 떄문에 사용하려는 상태를 직접 전달하는 것이 좋다.
      → ❌ BAD: useSelector((state) => state) / ✅ GOOD: useSelector((state) => state.languages)
    //component.jsx
    import { useSelector } from "react-redux";
    
    export const Components = () => {
    const languages = useSelector((state) => state.languages); 
    }
  4. 상태를 변화시키기 위해서는 useDispatch를 사용해서 action(액션)을 호출합니다.

    • 액션 type은 별도의 상수로 관리하는 것이 좋다. → ❌ BAD: add / ✅ GOOD: ADD_LANGUAGE
    //component.jsx
    import { useDispatch } from "react-redux";
    
    import { ADD_LANGUAGE } from "./action-type"
    
    export const Components = () => {
    const dispatch = useDispatch();
    
    const addLanguage = () => {
      dispatch({
        type: ADD_LANGUAGE,
        name: "JavaScript",
      });
    };
      return (
        <>
          <button onClick={addLanguage}>추가하기</button>
        </>
      );
    }
    
    //reducer.js
    import { ADD_LANGUAGE } from "./action-type";
    
    export default function reducer(state, action) {
    
      if (action.type === ADD_LANGUAGE) {
        return {
          ...state,
          languages: [
            ...state.languages,
            {
              name: action.name,
            },
          ],
        };
      }
    }
    
    // action-type.js
    export const ADD_LANGUAGE = "ADD_LANGUAGE";

폼의 데이터를 처리하기 어렵다.

UI 업데이트 돔에 있지 않은 데이터를 참조하는 훅이 있다. → useRef

useRef

  • UI 업데이트 돔에 있지 않는 데이터(렌더링에 필요하지 않는 값)를 참조하는 훅

폼과 관련된 데이터는 처리하기가 어렵다. 사용자의 이벤트를 처리하는건 어렵기 떄문에 이를 쉽게 지원하는 hook을 사용한다.

// input 요소를 생성하면 안에 value의 값이 있다.
const inputElement = document.querySelector('#myInput');
const inputValue = inputElement.value;

//useRef는 current라는 하나의 속성을 가지는 객체를 반환하는데,
//current 내부에 value의 값이 반환되도록 설계되어 있다.
inputRef = {
current: null,
};

사용 예시

const inputRef = useRef(null);

const addLanguage = () => {
  dispatch({
    type: ADD_LANGUAGE,
    name: inputRef.current.value,
  });
};

//input요소에 ref 속성에 ref를 연결한다.
<input type="text" ref={inputRef} onChange={addLanguage} />

redux 코드 개선하기

  1. import { ADD_LANGUAGE } from "./action-type 를 사용해서 매번 type을 가져오는 것은 번거롭다. 이를 개선해보자.
// action-type.js
export const ADD_LANGUAGE = "ADD_LANGUAGE";

//data가 무엇이 될지 모르기 때문에 매개변수로 받아서 처리한다.
export const dispatchAddLang = (data) => ({
  type: ADD_LANGUAGE,
  ...data,
});
  1. 1번 방식으로 하는 것은 사용자가 내부 로직을 이해하고 있어야 하는 종속성 문제가 있다. 이를 개선해보자.
// action-type.js
export const ADD_LANGUAGE = "ADD_LANGUAGE";

export const dispatchAddLang = (name, keyword) => ({
  type: ADD_LANGUAGE,
  name,
  keyword,
});
  1. 아래처럼 2번 방식으로 동작하는 액션이 많이 생기는 바람에 동일한 로직이 반복되어 작성되는 문제가 생겼다. 이를 개선해보자.
export const ADD_LANGUAGE = "ADD_LANGUAGE";
export const EDIT_LANGUAGE = "EDIT_LANGUAGE";

export const dispatchAddLang = (name, keyword) => ({
  type: ADD_LANGUAGE,
  name,
  keyword,
});

export const dispatchEditLang = (name, keyword) => ({
  type: EDIT_LANGUAGE,
  name,
  keyword,
});
profile
롤보다 개발이 재밌는 프론트엔드 개발자입니다 :D

0개의 댓글

관련 채용 정보