📝

4. 리액트에서 리덕스 사용하기(React)

리덕스 설치하기

# npx create-react-app . // 앞에서 쳤던 명령어 입니다. 설치가 선행되어야 합니다. npm i react-redux
 

Project Setting

javascript 코드는 모두 주석처리해놓고 이번에는 React로 구현해보겠습니다.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <link rel="icon" href="%PUBLIC_URL%/favicon.ico" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="theme-color" content="#000000" /> <meta name="description" content="Web site created using create-react-app" /> <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" /> <link rel="manifest" href="%PUBLIC_URL%/manifest.json" /> <title>React App</title> </head> <body> <div id="root"></div> </body> </html>
public / index.html
import React from "react"; import ReactDOM from "react-dom"; import App from "./App"; ReactDOM.render(<App />,document.getElementById("root"));
src / index.js
import React from "react"; const App = () => { return ( <div> <h2>딥러닝 개발자 무릎 담요</h2> <span> <strong>17,500</strong>원 </span> <div id="counter-box"> <button type="button"> MINUS </button> <span id="number">0</span> <button> PLUS </button> </div> <div> 총 수량 <strong id="quantity">0</strong> </div> <div> <strong id="total">17500</strong>원 </div> </div> ); }; export default App;
src / App.js
 

리덕스로 상태 관리하기

  1. store.js 파일을 만들고 그 안에 store, reducer, dispatch할 함수(action)를 만들어줍니다.
    1. import { createStore } from "redux"; const addNumber = () => { return { type: "ADD" }; }; const substractNumber = () => { return { type: "SUBSTRACT" }; }; const reducer = (state = 0, action) => { switch (action.type) { case "ADD": return state + 1; case "SUBSTRACT": return state - 1; default: return state; } }; const store = createStore(reducer); export default store;
      src / store.js
       
  1. index.js에 react-redux에서 제공하는 Provider 컴포넌트로 App 컴포넌트를 감싸줍니다. props로 store를 전달해줍니다.
    1. import React from "react"; import ReactDOM from "react-dom"; import App from "./App"; import { Provider } from "react-redux"; import store from "./store"; ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById("root") );
      src / index.js
  1. connect 함수를 App.js에 import 해줍니다. connect함수를 사용하면 스토어안에 있는 상태를 props로 넣어줄 수도 있고, 액션을 디스패치하는 함수도 props로 넣어줄 수 있습니다
  1. 스토어의 상태를 넘겨줄 mapStateToProps를 만들어줍니다.
    1. import React from "react"; import { connect } from "react-redux"; const App = ({ quantity }) => { return ( <div> <h2>딥러닝 개발자 무릎 담요</h2> <span> <strong>17,500</strong>원 </span> <div id="counter-box"> <button type="button"> MINUS </button> <span id="number">0</span> <button> PLUS </button> </div> <div> 총 수량 <strong id="quantity">0</strong> </div> <div> <strong id="total">17500</strong>원 </div> </div> ); }; function mapStateToProps(state) { return { quantity: state }; } export default connect(mapStateToProps)(App);
      src / App.js
  1. 액션 생성 함수를 넘겨줄 mapDispatchToProps 함수를 만들어줍니다. mapDispatchToProps 함수 내에서 액션을 디스패치하는 함수를 생성합니다. 이때 store.js에서 action creators(액션 생성함수) 인 addNumber, substractNumber 함수를 store.js에서 export 해준 뒤, App.js에 import 해줍니다.
    1. import React from "react"; import { connect } from "react-redux"; import { addNumber,substractNumber } from "./store"; const App = ({ quantity, addNumber, substractNumber }) => { return ( <div> <h2>딥러닝 개발자 무릎 담요</h2> <span> <strong>17,500</strong>원 </span> <div id="counter-box"> <button type="button"> MINUS </button> <span id="number">0</span> <button> PLUS </button> </div> <div> 총 수량 <strong id="quantity">0</strong> </div> <div> <strong id="total">17500</strong>원 </div> </div> ); }; const mapStateToProps = (state) => { return { quantity: state }; } const mapDisPatchToProps = (dispatch) => { return { plusNum: (text) => dispatch(addNumber(text)), minusNum: (text) => dispatch(substractNumber(text)), }; } export default connect(mapStateToProps, mapDisPatchToProps)(App);
      src / App.js
      import { createStore } from "redux"; export const addNumber = () => { return { type: "ADD" }; }; export const substractNumber = () => { return { type: "SUBSTRACT" }; }; const reducer = (state = 0, action) => { switch (action.type) { case "ADD": return state + 1; case "SUBSTRACT": return state - 1; default: return state; } }; const store = createStore(reducer); export default store;
      src / store.js
  1. state와 dispatch할 함수들을 UI에 넣어줍니다.
    1. import React from "react"; import { connect } from "react-redux"; import { addNumber,substractNumber } from "./store"; const App = ({ quantity, addNumber, substractNumber }) => { return ( <div> <h2>딥러닝 개발자 무릎 담요</h2> <span> <strong>17,500</strong>원 </span> <div id="counter-box"> <button type="button" id="minus" onClick={substractNumber}> MINUS </button> <span id="number">{quantity}</span> <button id="plus" onClick={addNumber}> PLUS </button> </div> <div> 총 수량 <strong id="quantity">{quantity}</strong> </div> <div> <strong id="total">{quantity * 17500}</strong>원 </div> </div> ); }; const mapStateToProps = (state) => { return { quantity: state }; } const mapDisPatchToProps = (dispatch) => { return { addNumber: (text) => dispatch(addNumber(text)), substractNumber: (text) => dispatch(substractNumber(text)), }; } export default connect(mapStateToProps, mapDisPatchToProps)(App);
      src / App.js
 
 

 
notion imagenotion image
힌트코드(props로 되어 있음)
import React from "react"; import { connect } from "react-redux"; import { getInputValue } from "./store"; function Four({ quantity }) { return ( <div> <h1>Four</h1> <p>{quantity}</p> </div> ); } function Three({ quantity }) { return ( <div> <h1>Three</h1> <Four quantity={quantity} /> </div> ); } function Two({ quantity }) { return ( <div> <h1>Two</h1> <Three quantity={quantity} /> </div> ); } function One({ quantity }) { return ( <div> <h1>One</h1> <Two quantity={quantity} /> </div> ); } function Input({ getInputValue }) { return ( <div> <input id="test" type="text" /> <button onClick={getInputValue}>눌러!</button> </div> ); } const App = ({ quantity, getInputValue }) => { return ( <div> <One quantity={quantity} /> <Input getInputValue={getInputValue} /> </div> ); }; const mapStateToProps = (state) => { return { quantity: state }; }; const mapDisPatchToProps = (dispatch) => { return { getInputValue: (text) => dispatch(getInputValue(text)), }; }; export default connect(mapStateToProps, mapDisPatchToProps)(App);
App.js
<!DOCTYPE html> <html> <head> <title>React App</title> <style> div { border: solid 10px blue; margin: 10px; padding: 10px; } </style> </head> <body> <div id="root"></div> </body> </html>
public/index.html
import { createStore } from "redux"; export const getInputValue = () => { return { type: "READ" }; }; const reducer = (state, action) => { const value = document.querySelector('#test').value; console.log(value); switch (action.type) { case "READ": return value; default: return state; } }; const store = createStore(reducer); export default store;
src/store.js
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; import { Provider } from "react-redux"; import store from "./store"; ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById("root") );
src/index.js
 

 
정답코드
<!DOCTYPE html> <html lang="en"> <head> <title>React App</title> <style> div { border: solid 10px blue; margin: 10px; padding: 10px; } </style> </head> <body> <noscript>You need to enable JavaScript to run this app.</noscript> <div id="root"></div> </body> </html>
public/index.html
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; import { Provider } from "react-redux"; import store from "./store"; ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById("root") );
src/index.js
import { createStore } from "redux"; const initailState={ quantity:0 } export const getInputValue = () => { return { type: "READ" }; }; export const setInputValue = () => { return { type: "WRITE" }; }; const reducer = (state=initailState, action) => { switch (action.type) { case "READ": console.log(...state) return {...state}; case "WRITE": console.log({...state}) return {...state, quantity:document.querySelector('#test').value} default: return state; } }; const store = createStore(reducer); export default store;
src/store.js
import React from "react"; import { connect, useDispatch } from "react-redux"; import store, { getInputValue,setInputValue } from "./store"; function Four() { const {quantity} = store.getState() return( <div> <h1>Four</h1> <p>{quantity}</p> </div> ) } function Three() { return( <div> <h1>Three</h1> <Four/> </div> ) } function Two() { return( <div> <h1>Two</h1> <Three/> </div> ) } function One() { return( <div> <h1>One</h1> <Two/> </div> ) } function Input() { const dispatch = useDispatch() return( <div> <input id="test" type="text"/> <button onClick={()=>dispatch(setInputValue())}>눌러!</button> </div> ) } const App = () => { return ( <div> <One/> <Input/> </div> ); }; const mapStateToProps = (state) => { return { quantity: state }; } const mapDisPatchToProps = (dispatch) => { return { getInputValue: (text) => dispatch(getInputValue(text)), }; } export default connect(mapStateToProps, mapDisPatchToProps)(App);
src/App.js