[React] Redux를 사용해보자

O_K·2022년 4월 27일
0

React

목록 보기
3/4
post-thumbnail

🌟Redux를 사용해보자

라이브러리 설치(redux, react-redux)

npm install redux react-redux

필요한 폴더 및 파일 생성하기

📂 src/actions
📂 src/reducers
📂 src/store

📂src/reducers 📂src/store 폴더 안에 index.js 파일을 만들기
📂src/store/index.js에서 store를 create 해준다
store 폴더를 만들지 말고 그냥 src/index.js에서 createStore해도 무방하다

// src/store/index.js

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

const store = createStore(rootReducer);

export default store;

App.js의 부모 컴포넌트로 Root.js를 따로 만들어서 사용했기 때문에
src폴더 바로 하위의 index.js가 이렇다 (App 대신 Root를 render하는 형태)

// src/index.js
ReactDOM.render(
    <Root />,
  document.getElementById('root')
);

아래와 같이 Root.js 파일에 react-redux Provider 를 Import 하여 감싸주었고 store를 전송하여 리액트에서 액션이 처리되었을 때 이벤트를 받아서 하위에 있는 다른 컴포넌트가 다시 렌더링 될 수 있도록 도와준다.

// src/client/Root.js

import React from "react";
import App from '../App';
import { BrowserRouter } from 'react-router-dom';
import { Provider } from 'react-redux';
import store from '../store';

const Root = () => (
  <BrowserRouter>
    <Provider store={store}>
    	<App/>
    </Provider>
  </BrowserRouter>
);

export default Root;

=> Root.js를 따로 만들지 않았다면 그냥 src/index.js에서 App을 Provider로 감싸주면 된다

Action 쪼개기

모든 action type을 하나의 파일에 담아서 import해서 사용하는 방법으로 하였다. (근데 그냥 해당 action파일에서 바로 지정해서 쓰는게 편리할 듯 하다.)

📂 src/actionsActionTypes.js라는 파일을 만들었다. 여기에 action type들을 지정해 줄 것이다.
이제 이 type으로 어떠한 reducer랑 연결될지 알 수 있다.

❗ 예시로 ADD_USERINFO라는 회원정보를 store에 저장하는 action을 만들어 보자 ❗

먼저 ActionTypes.js 에 type을 선언해준다

// src/actions/ActionTypes.js

export const ADD_USERINFO = "ADD_USERINFO";

📂 src/actions에 예시로 src/actions/user.js를 만들겠다.

  • 아까 ActionTypes.js에 지정했던 type을 사용
  • payload로 state에 저장할 userInfo를 지정
    (dispatch로 컴포넌트에서 action호출할 때 저장할 userInfo를 같이 넘겨줄 것이다
    -> 이걸 받아서 state로 저장하는 것!)
import { ADD_USERINFO } from "./ActionTypes";

export const addUserInfo = userInfo => ({
  type: ADD_USERINFO,
  payload: userInfo
});

reducer 쪼개기

rootReducer를 정의하고 세부 reducer를 정의하여
rootReducer에서 세부 reducer들을 combineReducers로 묶어준다

📂 src/reducers 에 예시로 src/reducers/user.js를 만들겠다

src/reducers/index.js에 모듈화 처리를 해줘야한다
=> 쪼갠 파일(user.js)을 import하여 combineReducers 로 묶어준다

앞으로 쪼갤 reducer 파일들을 combineReducers에 넣어주면 된다

import { combineReducers } from "redux";
import user from "./user"

const rootReducer = combineReducers({
  user : user,
})

export default rootReducer;

이제 state값을 변화시킬 reducer를 작성해 보자

action에서 payload로 받은 userInfo (data)를 userState의 userInfo에 저장해 줄 것이다!

이때 reducer는 불변성을 유지 하여아 하기 때문에 Spread 문법을 사용하였다.(혹은 concat, filter등 사용)

import * as type from "../actions/ActionTypes";

const userState = {
  userInfo: {},
};

const user = (state = userState, action = {}) => {
  switch (action.type) {
    case type.ADD_USERINFO:
      return {
        ...state,
        userInfo: { ...action.data }
      }

    default:
      return state;
  }
};


export default user;

action 호출 및 state 사용하기

action을 사용하는데에는 dispatchconnect 두 가지 방법이 있다.

1. dispatch로 호출

import store from '../store';
2) import { useSelector } from 'react-redux';

1) const userInfo = store.getState().user.userInfo;
2) const userInfo = useSelector( state => state.user.userInfo); 

store.dispatch({ type: ADD_USERINFO, data: userInfo });

type에 원하는 action type을 적고, data에 같이 전달할 payload를 보내주면 된다
state는
getState() 혹은useSelector 훅을 사용하여 접근할 수 있다

2. connect mapDispatchToProps로 호출

const mapStateToProps = (state) => {
  return {
    userInfo: state.user.userInfo,
  }
}

const mapDispatchToProps = (dispatch) => {
  return {
    addUserInfo: (userInfo) => dispatch({type:ADD_USERINFO, data: userInfo}),
  }
}

...


const TestComponent = () => {
  ...
}
  
  
// connect의 첫번째자리는 mapState, 두번째 자리는 mapDispatch (자리 위치 지켜줘야함)
// 마지막엔 연결할 컴포넌트 이름
export default connect(mapStateToProps, mapDispatchToProps)(TestComponent);

mapDispatchToProps로 dispatch를 할 수 있는데 이제 addUserInfo로 선언했으므로
컴포넌트 내에서 함수처럼 편하게 호출 가능하다!

ex) 
const userInfo = { name : '아무개', age: 30 }

addUserInfo(userInfo)

mapStateToPropsuserInfo로 state의 userInfo 값을 선언했으므로 컴포넌트 내에서 자유롭게 userInfo로 접근 가능!

profile
즐거운 개발자가 목표

0개의 댓글