-
[Redux] React-ReduxFront-End(Web)/React - 라이브러리들 2021. 2. 16. 18:58반응형
이전 포스팅에서 React+Redux 조합을 했듯이, Container 와 Presentational 기능분리의 번거로움이 있었다.
아마, 이를 Context API의 Provider, Consumer 개념처럼 Global State를 공급하는 역할을 이 react-redux가 해줄 것 같다.
💜 React? Redux? React-Redux?
React는 자바스크립트 기반 SPA 라이브러리, Redux는 React 뿐만 아니라 JS환경의 상태관리를 개선하기 위해 등장한 라이브러리다.
그렇다면, React 프로젝트 시 설치하는 Redux 말고, React-Redux 라이브러리의 의의는 무엇일까?- 의의
Redux 자체는 React, Angular, Vue 및 vanila JS 를 포함한 모든 UI 레이어 또는 프레임워크와 함께 사용 가능한 독립형 라이브러리이다.
모든 UI 프레임워크는 Redux를 사용하는 경우, UI 코드에서 'UI 바인딩 라이브러리' 를 사용하여 프레임워크와 Redux를 연결한다.
React-Redux 는 React 공식 Redux 바인딩 라이브러리이다. React + Redux를 사용하는 경우, 두 라이브러리를 바인딩해야 한다.
(출처: https://react-redux.js.org/introduction/why-use-react-redux )
한마디로, react-redux는 react와 redux를 바인딩(연결) 해주는 라이브러리 인 것이다.
- 설치
npm install react-redux
💜 React-Redux 주요 키워드
react-redux 에서 추가적으로 다루는 개념(키워드)들이 있다. 이에 대해 간단하게 정리해보았다.
위에서 언급했듯, React-Redux 가 제공하는 함수들은 대부분 React ~ Redux 간 연결기능을 주로 담당한다.
1. Provider
- Provider는 connect() 함수에 포장된 모든 컴포넌트가 Redux 스토어를 사용할 수 있게 해준다. (props로 스토어를 받음)
- 이같은 특징으로, 앱 최상위 레벨에서 Provider를 렌더링한다.
import React from "react"; import ReactDOM from "react-dom"; import { createStore } from "redux"; import reducers from "./reducers"; import { Provider } from "react-redux"; // Provider는 react-redux 라이브러리에서 가져옴 import App from "./components/App"; ReactDOM.render( // Provider 사용예시 <Provider store={createStore(reducers)}> <App /> </Provider>, document.querySelector("#root") );
2. connect()
- connect() 함수는 React 컴포넌트를 Redux 스토어와 연결한다.
- connect() 된 컴포넌트는 스토어에서 상태를 받아오거나, 디스패치 전달을 할 수 있다.
- connect() 문법: connect([mapStateToProps], [mapDispatchToProps])([전달할 컴포넌트명])
import React from 'react' import { connect } from 'react-redux; // connect 는 'react-redux' 라이브러리에서 가져옴 class Example extends Component { render(){ return( <> 예시 컴포넌트의 내용 </> ) } export default connect(null)(Example)
3. mapStateToProps
- connect() 함수의 첫 번째 인자로 전달된다.
- 스토어 내부의 모든 state 값을 인자로 받으며, 컴포넌트가 필요로 하는 데이터 객체를 반환한다.
- 연결된 컴포넌트에서 필요한 상태(state)를 선택하는데 사용된다. (= 상태 불러오기, getState)
- store 상태가 바뀔 때마다 호출된다. (= 구독, subscribe)
import React from 'react' import { connect } from 'react-redux; class Example extends Component { render(){ return( <> 예시 컴포넌트의 내용 </> ) } const mapStateToProps = (state) => { return { //받아올때 쓸 state의 이름' : state.'reducer에서 정한 데이터 이름' needData : state.needData } } export default connect(mapStateToProps)(Example)
mapStateToProps() 함수는 해당 컴포넌트에서 스토어의 상태를 받고자 할 때 사용된다. (useContext Hooks 적용과 유사)
스토어의 state를 인자로 받아, 우리가 사용하고자 하는 객체형태로 재구성한다. 이 객체는, Example 컴포넌트의 props로 전달된다.
4. mapDispatchToProps
- connect() 함수의 두 번째 인자로 전달된다.
- 스토어의 dispatch 함수를 인자로 받으며, 컴포넌트에 적용할 함수를 객체에 담아 전달한다.
import React from 'react' import { connect } from 'react-redux; class Example extends Component { render(){ return( <Example onClick={this.props.onClick}> 예시 컴포넌트의 내용 </Example> ) } const mapDispatchToProps = (dispatch) => { return { //받아올때 쓸 props(함수명)의 이름' : dispatch(action) 함수 onClick : () => { dispatch({ type: 'INCREMENT', size: 2, }) } } } export default connect(null, mapDispatchToProps)(Example)
mapDispatchToProps 역시 객체를 반환하는데, 특징은 키가 props명, 키값은 우리가 활용할 디스패치 함수가 된다.
💜 React-Redux 적용하기
기존에 제작한 Container 컴포넌트들을 각각 React-Redux 를 통해 간소화하는 작업을 해보겠다.
// AddNumberCon.js import React from 'react' import AddNumber from '../components/AddNumber'; import store from '../Store'; const AddNumberCon = () => { return ( <AddNumber onClick={(size) => { store.dispatch({ type: 'INCREMENT', size, }) }}/> ) }
// ShowNumberCon.js import React, { useState } from 'react'; import store from '../Store'; import ShowNumber from '../components/ShowNumber'; const ShowNumberCon = () => { const [number, setNumber] = useState(0); store.subscribe(() => { setNumber(store.getState().number) }) return ( <ShowNumber number={number} /> ) }
- React-Redux 적용
1. Provider 설정
// index.js import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; import { Provider } from 'react-redux'; import store from './Store'; import './index.css'; import reportWebVitals from './reportWebVitals'; ReactDOM.render( <Provider store={store}> <App /> </Provider> , document.getElementById('root') ); reportWebVitals();
앱 최상위에서 다음과 같이 <Provider>로 감싸준다. props는 스토어를 지정해주면 된다.
2. Container 컴포넌트의 connect() 적용
1) mapStateToProps : map + Redux-State + to + React-Props
// ShowNumberCon.js import { connect } from 'react-redux'; import ShowNumber from '../components/ShowNumber'; const mapStateToProps = (state) => { return { number: state.number, } } export default connect(mapStateToProps)(ShowNumber);
상태값을 활용하는 <ShowNumber> 컴포넌트의 경우, mapStateToProps 를 통해 스토어의 상태를 전달한다.
스토어 상태 중, 우리가 필요한 number에 대해서만 재가공한 객체가 props로 전달된다.
2) mapDispatchToProps : map + Redux-Dispatch + to + React-Props
// AddNumberCon.js import { connect } from 'react-redux'; import AddNumber from '../components/AddNumber'; const mapDispatchToProps = (dispatch) => { return { onClick: (size) => { dispatch({ type: 'INCREMENT', size, }) } } } export default connect(null, mapDispatchToProps)(AddNumber);
이벤트 핸들러로 디스패치를 활용하는 <AddNumber> 컴포넌트의 경우, mapDispatchToProps 를 통해 디스패치 함수를 전달한다.
객체 형태로 props가 전달되며, 키는 props명, 키값은 dispatch(action) 함수가 들어간다.
확실히 Context API 에 비해 러닝커브가 높다는 것이 느껴졌다. (useReducer 를 제외한 비교이기는 하나)
무엇보다, Container 컴포넌트가 아직 존재한다는 것에 대해 의문이 들기도 한다. (mapStateToProps, mapDispatchToProps)
또한, 생활코딩 강의는 클래스형 컴포넌트 위주로 이루어졌기에, 함수형에 관한 공부도 추가하면서 좀 더 원활하고 효율적으로 Redux를 활용할 수 있는 방법에 대해 고민해봐야겠다.
[출처]
- Redux 공식문서: react-redux.js.org/introduction/quick-start
- mokyungg 님의 블로그: velog.io/@mokyoungg/Redux-react-redux-react-redux
반응형'Front-End(Web) > React - 라이브러리들' 카테고리의 다른 글
[Redux] 미들웨어(Middleware) (0) 2021.02.18 [Redux] Hooks - useSelector, useDispatch (0) 2021.02.17 [Redux] React + Redux App 만들기(생활코딩) (0) 2021.02.16 [Redux] 순수 Redux App 만들기(생활코딩) (0) 2021.02.15 [Redux] Redux 기본개념 (0) 2021.02.15