[React] react-redux , redux, redux-toolkit 사용법

민갱·2023년 9월 13일
0

React

목록 보기
18/20

리덕스 부터 시작을 해서 toolkit까지 사용해봤는데,,ㅎㅎ
결국엔 toolkit으로 기계처럼 사용하고 있네요ㅎ
카운터가 가장 보편화된 예시인데, 실제로 사용하면서 비동기처리를 필요했던 부분이 있는데 내용은 차후에 다시 정리해봐야겠다

설치

npm install redux
npm install react-redux

Redux 사용하기

상태 관리를 위해서 Redux를 사용하려고 하는것!
useState를 사용할 때 setState를 이용하여 값을 변경하는 것처럼 모든 파일에서 ( = 전역에서) 접근할 수 있는 state가 있고 그걸 원하는 값으로 변경하는 기능만 있으면 된다.

용어

Redux 기본 용어

  • Store

    • 스토어는 컴포넌트의 상태를 관리하는 저장소다. 하나의 프로젝트는 하나의 스토어만 가질 수 있다.
  • Action

    • 스토어의 상태를 변경하기 위해서는, 액션을 생성해야한다. 액션은 객체이며, 반드시 type을 가져야 한다. 액션 객체는 액션생성함수에 의해서 만들어진다.
  • Reducer

    • 리듀서는 현재 상태와 액션 객체를 받아 새로운 상태를 리턴하는 함수다.
  • Dispatch

    • 디스패치는 스토어의 내장 함수 중 하나이며, 액션 객체를 넘겨줘 상태를 업데이트 시켜주는 역할을 한다.
  • Subscribe

    • 스토어의 내장 함수 중 하나로, 리듀서가 호출될 때 서브스크라이브된 함수 및 객체를 호출한다.

파일

위에서 설명한 3가지 이름으로 파일을 만들어 사용한다.
파일명은 자유지만 보통 이렇게 사용한다.

store.js

import { createStore } from "redux";
import rootReducer from "./rootReducer";

const store = createStore(rootReducer);

export default store;

store.js에서는 다음과 같은 코드로 store를 생성해준다.
createStore는 첫번째 인자로 reducer를 받는다.
여기서는 rootReducer이다.

rootReducer.js

const initialState = {
  data: [],
};

const rootReducer = (state = initialState, action) => {
  switch (action.type) {
    case "setData":
      return { ...state, data: action.payload };
    default:
      return state;
  }
};

export default rootReducer;

rootReducer에는 state와 action이 들어간다.
state에는 초기값을 지정해줄 수 있다.
이 경우에 action을 setState와 같은 기능을 하는 setData를 만들어주었다.
기존에 state 객체를 복사해와서 그안에 data라는 key와 action에서 받아오는 payload를 value로 state를 바꿔주는 역할을 한다.

action.js

export const setData = data => ({
  type: "setData",
  payload: perData,
});

setData는 perData라는 새로 변경해줄 데이터를 받아서 reducer에 전달해주는 action이다.

state사용하기

index.jsx
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import { Provider } from "react-redux";
import store from "redux/store";

ReactDOM.render(
  <Provider store={store}>
    <React.StrictMode>
        <App />
    </React.StrictMode>
  </Provider>,
  document.getElementById("root")
);
  • index.js파일에서 Provider를 통해 store를 하위 컴포넌트들에 전달해준다.
  • 감싸줘야한다!!!
import { connect } from "react-redux";

const mapStateToProps = state => {
  return {
    reduxData: state.data,
  };
};
const Page = ({ reduxData }) => {
	...
  return (
    ...
  );
};

export default connect(mapStateToProps)(Page);

컴포넌트에서 store에 있는 state(이 경우는 reduxData)를 사용하려면 connect함수를 이용하여 mapStateToProps와 Page를 연결해줘야 한다. 연결하면 해당 컴포넌트에서 props.reduxData로 state를 사용할 수 있게 된다.

store에 있는 state를 변경

import React, { useState, useEffect } from "react";
import { getSearchData } from "api";
import { Button } from "components";
import { connect } from "react-redux";
import { setData } from "redux/actions";

const mapDispatchToProps = dispatch => {
  return {
    setData: data => dispatch(setData(data)),
  };
};

const StateEdit = ({ setData }) => {

  const searchHandler = async () => {
    if (targetData) {
      const data = await getSearchData(targetData);
      console.log(data);
      setData(data.data);
    }
  };

  return (
    <>
        <div className="button" onClick={() => searchHandler()}>
            <span className="text">출력</span>
          </Button>
    </>
  );
};

export default connect(null, mapDispatchToProps)(StateEdit);

redux-toolkit 사용법

설치

npm install @reduxjs/toolkit

Store 연동하기

Provider는 react-redux에서 리액트 앱에 스토어를 연동할 수 있게 해주는 컴포넌트다. 아래와 같이 Provider 컴포넌트를 불러와 연동할 컴포넌트를 감싸준 뒤, Provider의 props로 사용할 스토어를 지정해주면 된다.

// App.jsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'

import { Provider } from "react-redux";
import store from "./store/store.js";

ReactDOM.createRoot(document.getElementById('root')).render(
    <Provider store={store}>
      <App />
    </Provider>
)

Store 만들기

먼저 store.js에 configureStore()로 스토어를 만들어주자.

// store.js

import { configureStore } from '@reduxjs/toolkit';

export const store = configureStore({
	reducer: counterSlice,
    middleware: [...middlewares]
})

기존 리덕스에서는 스토어 생성 후 미들웨어가 한 개 이상이라면, 여러 메서드를 통해 긴 코드를 작성해야 했다.

configureStore()는 별도의 메서드 없이 바로 미들웨어를 추가할 수 있다는 장점이 있다.

createSlice 생성

기존 리덕스에서는 액션을 디스패치하기 위한 별도의 함수가 필요했고, 액션의 객체를 리듀서를 통해 리턴하는 구조였다.

createSlice()는 액션에 대한 함수 설정과 리듀서를 따로 생성하지 않아도 된다.

아래는 createSlice()를 사용한 카운트업 코드와 그에 대한 설명이다.

// AllCheck.jsx


import { createSlice } from '@reduxjs/toolkit'
export const counterSlice = createSlice({
  name: 'counter',
  initialState: { value: 0 },
  reducers: {
    plus: state => {
      state.value += 1
    },
    minus: state => {
      state.value -= 1
    },
  },
})

export const { plus, minus } = counterSlice.actions; 
export default counterSlice.reducer;
  • initialState를 통해 state의 처음 상태를 정의한다.
  • reducers에서 액션을 설정한다.
  • plus와 mius를 export해서 App.jsx에 import한다.
  • slice는 slice.reducer로 내보낸다. store.js는 위 파일을 전부 리듀서로 받는다.

useSelector, useDispatch 사용

useSelector()는 기존 리덕스의 connect()를 이용하지 않고 리덕스의 상태를 조회할 수 있다.

useDispatch()는 생성한 액션을 발생시키며, 액션생성 함수를 가져온다. 위 설명의 디스패치와 같다고 보면 된다.

아래는 useSelector()와 useDispatch()에 대한 설명이다.

import React from 'react'
import { useDispatch, useSelector } from 'react-redux';
import { plus, minus } from './counter/countSlice01';

export default function App() {
  const count = useSelector(state => state.counter.value);
  const dispatch = useDispatch();

  return (
    <div>
      <button onClick={() => dispatch(minus())}>-</button>
      Value: { count } 
      <button onClick={() => dispatch(plus())}>+</button>
    </div>
  );
}

useSelector()로 스토어에서 현재 상태 값을 가져온다.
useDispatch()를 통해 변경되는 값을 스토어로 전달한다.

profile
가보자고

0개의 댓글

관련 채용 정보