TIL #31 | React에서 Redux 사용하기(1)

kibi·2023년 11월 22일
1

TIL (Today I Learned)

목록 보기
30/83

Redux란?

자바스크립트 애플리케이션을 위한 상태 관리 라이브러리

state 내부 상태 관리
props 구성요소가 서로 통신하는 방법 - 상위 구성 요소에서 아래쪽으로 흐른다.

Redux Flow

View -> dispatch(aciton) -> midderware -> Reducer -> Redux Store -> React Component -> View

  1. View에서 액션이 일어난다.
  2. dispatch에서 action이 발생한다.
  3. action에 의한 reducer 함수가 실행되기 전에 middleware가 작동한다.
  4. middleware에서 명령내린 일을 수행하고 난 뒤, reducer 함수를 실행한다.
  5. reducer의 실행결과 store에 새로운 값을 지정한다.
  6. store의 state에 subscribe를 하고 있던 UI에 변경된 값을 준다.

파일 구조

  • redux
    - config : 리덕스 설정과 관련된 파일들을 모아놓을 폴더
    - configStore.js : 중앙 state 관리소인 state를 만드는 설정 코드들이 있는 파일
    - modules : 모듈화 된 리듀서를 모아놓은 폴더
    - reducer: state를 action의 type에 따라 변경하는 함수 구성

순서

패키지 설치: yarn add react-redux

기본적인 구성 순서
1. reducer 파일 생성
2. store 생성 : const store = creatStore(counter)
3. getState() : value={store.getState()}
4. dispatch () : store.dispatch({type: "지정한 type"})
5. subscrive()를 사용하여 반영 : index.js => store.subscribe(render)

createStore()와 combineReducers()

createStore()은 store을 생성하는 역할을 하고,
combineReducers()는 각각 생성된 리듀서를 합치는 역할을 한다.

// redux > config > configStore.js - 중앙 데이터 관리소(store) 설정

import { createStore } from "redux";
import { combineReducers } from "redux";
import counter from "../modules/counter";
import users from "../modules/users";
import todos from "../modules/todos";

const rootReducer = combineReducers({
  counter,
  users,
  todos,
});
const store = createStore(rootReducer);

export default store;

Reducer

리듀서란 state를 action의 type에 따라 변경하는 함수이다.

action 발생 시 type과 payload를 받아와 처리하여 store로 넘겨준다.

(1) 액션 타입 정의

  • 사용할 string 값을 변수에 저장해서 오타를 방지하고 유지보수를 수월하게 할 수 있도록 한다.
// redux > modulwa > counter.js
const PLUS_ONE = "PLUS_ONE";
const MINUS_ONE = "counter/MINUS_ONE";
const PLUS_N = "counter/PLUS_N";
const MINUS_N = "counter/MINUS_N";

(2) 액션 생성자 (액션 생성 함수) : action value를 반환하는 함수 정의

  • 액션 객체는 반드시 type이라는 key를 가져야 한다.
    - (리듀서는 객체 안에서 type이라는 key를 보기 때문)
export const plusOne = () => {
  return { type: PLUS_ONE };
};

export const minusOne = () => {
  return { type: MINUS_ONE };
};

export const plusN = (payload) => {
  return {
    type: PLUS_N,
    payload,
  };
};

export const minusN = (payload) => {
  return {
    type: MINUS_N,
    payload,
  };
};

Payload

action 객체는 action type을 payload 만큼 처리한다.
-> 리듀서로 보내는 액션 객체에 어떤 정보를 같이 담아보내고자 한다면 payload를 이용한다.

왜 액션 타입을 정하고 생성자 함수를 사용할까?
-> 리덕스를 사용할 때 대부분의 사람들이 사용하는 Ducks 패턴을 적용하는 것이 좋기 때문이다.

Ducks 패턴

리덕스의 구성요소를 패턴화한 것
1) Reducer 함수를 export default 한다.
2) Action creator 함수들을 export 한다.
3) Action type은 app/reduce/ACTION_TYPE 형태로 작성한다.

(3) 리듀서 함수 생성

// 초기 상태값(state)
const initialState = {
  number: 0,
};


// input : state와 action(type과 value를 가짐)
const counter = (state = initialState, action) => {
  switch (action.type) {
    case PLUS_ONE:
      return { number: state.number + 1 };
    case MINUS_ONE:
      return { number: state.number - 1 };
    case PLUS_N:
      return {
        number: state.number + action.payload,
      };
    case MINUS_N:
      return { number: state.number - action.payload };
    default:
      return state;
  }
};

export default counter;

리듀서는 state와 action을 받아서 사용한다.
(action은 type과 payload를 가지고 있다.)
dispatch로 action을 받아오고 action.type에 따라 state와 action.payload를 사용하여 값을 리턴할 수 있다.
일반적으로 switch문을 사용하며 반드시 default를 정해주어야 한다.

Redux Provider

Redux Store 저장소에 액세스해야 하는 모든 중첩 구성 요소에서 Redux Store 저장소를 사용할 수 있도록 한다.

최상위에 존재하도록 Provider로 하위 컴포넌트를 감싸준다.

  • 하위 컴포넌트에서 store를 사용할 수 있다.
//index.js
import { Provider } from "react-redux";

const root = ReactDOM.createRoot(document.getElementById("root"));

root.render(
  <Provider store={store}>
    <App />
  </Provider>
);

useSelector

store에 저장된 데이터 상태를 가쟈온다.

  • useSelector로 값을 가져올 경우 state는 store를 의미한다.
  • 구독하고 있는 대상의 값이 바뀌면 리렌더링 된다.
    -> 불필요한 리렌더링을 방지하기 위해 구독 대상을 명확히 하는 것이 좋다
  const counter = useSelector((state) => {
    return state.counter; // 구독 대상 (바뀌면 리렌더링)
  });

useDispatch

데이터 상태 변경을 요청한다.

  // useDispatch()
  const dispatch = useDispatch();
  • action type과 payload를 넘겨줘서 dispatch로 상태변경을 요청한다.
  • 액션 생성자를 호출한다.
        onClick={() => {
          dispatch(plusN((number)));
        }}

0개의 댓글