출처는 redux 공식문서입니다.
https://ko.redux.js.org/
react를 잘 쓰려면 redux를 알아야 한다.
그러나 redux는 어렵다. 왜 어려울까.
개인적으로 2번의 문제가 redux 공부를 방해하였다.
새로운 단어, 개념 등이 한꺼번에 쏟아져 나와 정신을 못 차렸다.
이를 정리하기 위해 글을 쓴다.
redux 개념에 앞서 redux와 react를 연결해주는 react-redux의 개념을 먼저 아는 것이 도움이 된다.
처음 Redux를 알게 된 뒤 내가 가진 가장 큰 오해는 redux가 react의 아쉬운 점을 보완해주기 위해 탄생한 라이브러리라고 이해했다는 것이다. 물론, redux는 react를 보완해주는 측면은 있지만 react와 redux는 전혀 다른(연관이 없는) 라이브러리이다.
Redux는 자바스크립트 앱을 위해 탄생하였다.(React 때문이 아니다.)
Redux는 자바스크립트 앱을 위한 예측 가능한 상태 컨테이너
출처 : https://ko.redux.js.org/
그리고 react에서 redux를 사용하려면 redux도 설치하고 react-redux도 설치해야한다.
라이브러리를 2개나 설치하는 만큼, 라이브러리에서 파생되는 개념들도 2배다.
(위에서도 이야기했지만 그래서 엄청 헷갈린다.)
redux는 상태 관리를 쓰는거라면 react-redux는 무엇인가?
React는 SPA를 만들기 위해 사용된다.
Ract는 자체적으로 state(와 props)를 관리할 수 있지만 컴포넌트가 많아지고 깊어지면 state의 값을 관리하기가 피곤하다.
redux는 state를 편하게 관리하기 위한 목적으로 사용된다.
그렇다면 react-redux는 왜 쓰는가?
Why Use React Redux?
Redux 자체는 React, Angular, Vue, Ember 및 vanilla JS를 포함한 모든 UI 레이어 또는 프레임워크와 함께
사용할 수 있는 독립형 라이브러리이다. Redux와 React는 일반적으로 함께 사용되지만 서로 독립적입니다.
모든 종류의 UI 프레임 워크와 함께 Redux를 사용하는 경우 일반적으로 UI 코드에서 'UI 바인딩' 라이브러리를 사용하여
Redux를 UI 프레임 워크와 연결합니다. React Redux는 React용 공식 Redux UI 바인딩 라이브러리입니다.
Redux와 React를 함께 사용하는 경우 React Redux를 사용하여 이 두 라이브러리를 바인딩해야합니다.
출처: https://react-redux.js.org/introduction/why-use-react-redux
한마디로, react-redux는 react와 redux를 연결해주는 라이브러리이다.
react-redux가 제공하는 함수는 대부분 연결하는 기능을 제공한다.
import React from "react"; import ReactDOM from "react-dom";
// Provider는 react-redux 라이브러리에서 가져온다. import { Provider } from "react-redux"; // createStore는 redux에서 가져온다. import { createStore } from "redux"; import App from "./components/App"; import reducers from "./reducers";
ReactDOM.render( // connect()함수에 포함된 모든 컴포넌트가 redux store를 사용할 수 있기 위해, // Provider는 최상위 레벨에서 렌더링 된다 // provider의 props로 store가 있으며 redux store를 할당한다. <Provider store={createStore(reducers)}> <App /> </Provider>, document.querySelector("#root") );
Provider는 최상위 레벨('#root'가 있는 index.js)에서 App.js 컴포넌트를 감싼다.
이를 통해 connect()가 포함된 모든 컴포넌트가 redux store를 사용할 수 있게 된다.
import React from 'react' // react-redux 라이브러리에서 connect를 가져옴 import { connect } from 'react-redux;
class 예시컴포넌트 extends Component { render(){ return( <> <div> 예시 컴포넌트의 내용 <div> </> ) }
// connect()로 컴포넌트와 redux store 연결하기 export default connect(null)(예시컴포넌트)
정리하자면
1. connect() 함수를 'react-redux' 라이브러리에서 가져온다.
2. 'export default connect()(예시컴포넌트)' 형태로 컴포넌트를 connect()함수로 연결한다.
3. (connect()의 첫번째 인자로 mapStateToProps, 두번째 인자로는 reducer에 전달할 action을 넣는다.)
보기엔 어색하지만,
function connect()()는 유효한 자바스크립트 코드이다.
function connect(){ return function(){ return '안녕' } }
connect()() // '안녕'
import React from 'react' // react-redux 라이브러리에서 connect를 가져옴 import { connect } from 'react-redux;
class 예시컴포넌트 extends Component { render(){ return( <> <div> 예시 컴포넌트의 내용 <div> </> ) } //컴포넌트 생성 코드 종료.
// 컴포넌트 생성 코드의 외부에서 mapStateToProps 사용(store 에서 데이터 받아오기) const mapStateToProps = (state) => { return { //받아올때 쓸 state의 이름' : state.'reducer에서 정한 데이터 이름' needData : state.needData } }
// connect()로 컴포넌트와 redux store 연결하기 // connect()의 첫번째 인자, mapStateToProps는 store에서 state를 받아온다. export default connect(mapStateToProps)(예시컴포넌트)
const mapStateToProps = (state) => { console.log(state) // store에 있는 모든 state가 console에 보임 }
const mapStateToProps = (state) => { return { //사용자지정 이름(키) : store에서 사용자가 원하는 부분(값) 조던 : state.조던 // 전체 state 중, '조던'이라는 키의 값을 '조던'에 할당함. }
store에 있는 특정 키의 값을 원하는 이름에 할당하고, 객체의 형태로 반환한다.
mapStateToProps는 컴포넌트에서 필요한 state를 store에서 가져와 객체의 형태로 만들어준다.
이제 해당 컴포넌트에서 console.log(props)를 찍어보면 {조던 : 할당 된 값} 의 형태가 뜬다.
부모 컴포넌트가 아닌 store에서 state를 props로 받아오게 된다.
import React from "react";
// connect는 react-redux 라이브러리에서 가져온다. import { connect } from "react-redux"; import { action#1 } from "../actions";
// 1-1. Component 생성 코드(함수형 컴포넌트로 state값과 action#1을 받아온다.) const 예시컴포넌트 = ({needData, aciont#1}) => { return( <div> <button onClick={()=> {action#1}> //클릭시, action을 reducer로 보내기 액션 보내기! </button> <div> {needData} //store에서 받은 데이터 </div> </div> ) } //이 부분에서 컴포넌트 생성 코드는 끝난다.
// 1-2. Component 생성 코드(클래스형 컴포넌트) class 예시컴포넌트 extends Component { render(){ return( <div> <button onClick={()=>this.props.action#1} //클릭시, action을 reducer로 보내기 액션보내기! </button> <div> {this.props.needData} //store에서 받은 데이터 </div> </div> ) } //이 부분에서 컴포넌트 생성 코드는 끝난다.
// 컴포넌트 생성 코드의 외부에서 // mapStateToProps 사용(store 에서 데이터 받아오기) const mapStateToProps = (state) => { return { //받아올때 쓸 state의 이름' : state.'reducer에서 정한 데이터 이름' needData : state.needData } }
// connect()로 컴포넌트와 redux store 연결하기 // connect()의 첫번째 인자, mapStateToProps는 store에서 state를 받아오고 // connect()의 두번째 인자, {action#1}는 store에 action#1을 보낸다.(dispatch) export default connect(mapStateToProps, { action#1 })(예시컴포넌트)
connect()함수로 컴포넌트를 연결하였다면..
클래스형 컴포넌트 : 컴포넌트 생성 코드에서 console.log(this.props)
함수형 컴포넌트 : 컴포넌트 생성 코드에서 console.log(props)
mapStateToProps 코드에선 console.log(state),로 확인해보는 것이 좋다.
react-redux의 모든 개념을 담은 글은 아니다.
내가 써보고 이해한 만큼만 작성하였다.
감사합니다.