본문 바로가기

Redux

React → Redux | Redux 101 (2/2)

반응형

Redux | NomardCoder

* React Redux

(0. Setup)

- redux는 vanillaJS part에서 이미 설치했음 (package확인)

- react-redux, react-router-dom 설치하기 (npm istall react-redux react-router-dom)

 

 

1. react, router 로 todo 만들기

 

App.js에 router로 Home, Detaile 페이지 생성

 

Router

import React from "react";
import { HashRouter as Router, Route } from "react-router-dom";
import Home from "../routes/Home";
import Detail from "../routes/Detail";

function App() {
  return (
    <Router>
      <Route path="/" exact component={Home}></Route>
      <Route path="/:id" component={Detail}></Route>
    </Router>
  );
}

export default App;

 

React

Home 페이지에 todo form

 

import React, { useState } from "react";

function Home() {
  const [text, setText] = useState("");

  function onChange(e) {
    setText(e.target.value);
  }

  function onSubmit(e) {
    e.preventDefault();
    setText("");
  }

  return (
    <>
      <h1>To Do</h1>
      <form onSubmit={onSubmit}>
        <input type="text" value={text} onChange={onChange} />
        <button>Add</button>
      </form>
      <ul></ul>
    </>
  );
}

export default Home;

 

Redux

store 생성

 

import { createStore } from "redux";

const ADD = "ADD";
const DELETE = "DELETE";

export const addToDo = (text) => {
  return {
    type: ADD,
    text,
  };
};

export const deletToDo = (id) => {
  return {
    type: DELETE,
    id,
  };
};

const reducer = (state = [], action) => {
  switch (action.type) {
    case ADD:
      return [...state, { text: action.text, id: Date.now() }];
    case DELETE:
      return state.filter((toDo) => toDo.id !== action.id);
    default:
      return state;
  }
};

const store = createStore(reducer);

export default store;

 

 

2. react + redux

- connecting the Store

 

react는 모든 페이지를 render하지 않고 변화되는 부분만 render 된다

 

index에서 내 application 연결하기

 

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

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById("root")
);

 

 

3. redux - connect

 

conntect - components들을 store에 연결시켜줌

- store로부터 state 가져올 수 있게 Home과 store 연결

- conntect는 두 개의 argument를 가짐 (state, dispatch)

 

3-1) connect/state - redux state로부터 정보 가져오기 ( getState() -> mapStateToProps() )

 

 

Connect: Extracting Data with mapStateToProps | React Redux

Connect: Extracting Data with mapStateToProps

react-redux.js.org

 

//Home.js
function getCurrentState(state, ownProps) {
  console.log(state, ownProps);
}

export default connect(getCurrentState)(Home);

 

- state - store로부터 가져온 state

- ownProps - Home에게 준 props

 

+) ownProps 통해 원하는 props를 전달할 수 있다.

 

내가 이해한 바로 정리> provider의 store로 내부 components와 store을 연결시켜서 사용 → store과 component를 연결하기 위해 mapStateToProps 함수 사용→  연결로 store로부터 state를 가져올 수 있음 (store.getState() 역할과 비슷)

 

3-2) connect/dispatch -  ( dispatch() -> mapDispatchToProps() )

 

- dispatch - store로부터 전달된 dispatch

- ownProps - Home에게 준 props

 

 

Connect: Dispatching Actions with mapDispatchToProps | React Redux

Connect: Dispatching Actions with mapDispatchToProps

react-redux.js.org

 

import React, { useState } from "react";
import { connect } from "react-redux";
import { addToDo } from "../store";

function Home({ toDos, dispatch }) {
  const [text, setText] = useState("");

  function onChange(e) {
    setText(e.target.value);
  }

  function onSubmit(e) {
    e.preventDefault();
    setText("");
    dispatch(addToDo(text));
  }

  return (
    <>
      <h1>To Do</h1>
      <form onSubmit={onSubmit}>
        <input type="text" value={text} onChange={onChange} />
        <button>Add</button>
      </form>
      <ul>{JSON.stringify(toDos)}</ul>
    </>
  );
}

//mapStateToProps
function mapStateToProps(state) {
  return {
    toDos: state,
  };
}

function mapDispatchToProps(dispatch) {
  return { dispatch };
}

export default connect(mapStateToProps, mapDispatchToProps)(Home);

 

↓ `addToDo`라는 props 만들어서 사용하기 (refactoring)

 

//store.js
export const actionCreators = {
  addToDo,
  deletToDo,
};

//Home.js
import React, { useState } from "react";
import { connect } from "react-redux";
import { actionCreators } from "../store";

function Home({ toDos, addToDo }) {
  const [text, setText] = useState("");

  function onChange(e) {
    setText(e.target.value);
  }

  function onSubmit(e) {
    e.preventDefault();
    addToDo(text);
    setText("");
  }

  return (
    <>
      <h1>To Do</h1>
      <form onSubmit={onSubmit}>
        <input type="text" value={text} onChange={onChange} />
        <button>Add</button>
      </form>
      <ul>{JSON.stringify(toDos)}</ul>
    </>
  );
}

//mapStateToProps
function mapStateToProps(state) {
  return {
    toDos: state,
  };
}

function mapDispatchToProps(dispatch) {
  return {
    addToDo: (text) => dispatch(actionCreators.addToDo(text)),
  };
}

export default connect(mapStateToProps, mapDispatchToProps)(Home);

 

- Home component는 직접 dispatch나 action Creators를 처리할 필요 없이, props로 전달해주기

 

 

4. toDo 출력, delete 기능 

 

//Home.js
<ul>
  {toDos.map((toDo) => (
    <ToDo {...toDo} key={toDo.id} />
  ))}
</ul>

 

- mapStateToProps()로 state가져와서 toDo에 출력하기 

 

 

//toDo.js
import React from "react";
import { connect } from "react-redux";
import { actionCreators } from "../store";

function ToDo({ text, onBtnClick }) {
  return (
    <li>
      {text} <button onClick={onBtnClick}>btn</button>
    </li>
  );
}

function mapDispatchToProps(dispatch, ownProps) {
  return {
    onBtnClick: () => dispatch(actionCreators.deletToDo(ownProps.id)),
  };
}

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

 

- mapDispatchToProps()로 delete기능 

'Redux' 카테고리의 다른 글

Redux Toolkit  (0) 2021.05.05
[Redux 강의노트] Redux Middleware | redux-saga  (0) 2021.01.13
[Redux 강의노트] Redux Middleware | logger, thunk  (0) 2021.01.09
[Redux강의노트] Redux  (0) 2021.01.03
VanillaJS → Redux | Redux 101 (1/2)  (0) 2020.11.18