react

react-redux 설치 및 이용방법

YG - 96년생 , 강아지 있음, 개발자 희망 2022. 2. 11. 13:54

설치방법

npm i redux react-redux

 

store 파일 만들기

import { createStore } from 'redux';

const ADD = 'add';
const DELETE = 'delete';

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

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

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

const store = createStore(reducer);

export default store;

예제입니다.

createStore(reducer)을 한 후 export 해주어야 합니다.

 

Provider 로 감싸주기

import { render } from 'react-dom';
import { Provider } from 'react-redux';
import App from './App';
import store from './store';

const rootElement = document.getElementById('root');
render(
  <Provider store={store}>
    <App />
  </Provider>,
  rootElement
);

react-redux에는 Provider라는 컴포넌트가 있는데 이것을 사용할 부분에 감싸주어야 합니다. 

그리고 이용할 store을 연결해주면 됩니다.

 

작동원리는 리액트는 index.js에서부터 모든 컴포넌트를 렌더링하기 때문에 이 전역변수는 App.js 밖에 있어야 하기 때문입니다.

 

getState()를 리액트에서 이용하는 방법

자바스크립트에서는 store.getState()를 하면 되었엇지만 리액트에서는 조금 다릅니다.

 

 mapStateToProps(state){return state이름:state} 를 컴포넌트 밖에서 적어줍니다. 함수 이름은 마음대로 지으셔도 상관 없습니다.

 

그리고 redux의 connect를 이용하여  connect(만든함수) (컴포넌트 이름) 으로 연결해주시면 해당 컴포넌트에 store에 잇는 전역변수가 props로 들어오게 되어서 사용할 수 있게 됩니다.

 

import React, { useState } from 'react';
import { connect } from 'react-redux';

function Home({ toDos }) {
  const [text, setText] = useState('');
  const onChange = (e) => {
    setText(e.target.value);
  };
  const 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>
      <ul>{JSON.stringify(toDos)}</ul>
    </>
  );
}

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

export default connect(mapStateToProps)(Home);

 

function Home(props) {
  console.log(props);

props를 콘솔로그하였을 때 dispatch와 toDos 와 같이 redux 에서 사용할수 있는 함수와 같이 들어오게 됩니다.

https://react-redux.js.org/using-react-redux/connect-mapstate

 

Connect: Extracting Data with mapStateToProps | React Redux

Usage > mapState: options for reading state with connect

react-redux.js.org

 

dispatch() 를 리액트에서 이용하는 방법

 

 

connect 함수의 두번째 인자는 dispatch를 전달할 수 있습니다.

 

dispatch를 함수로 보내고 컴포넌트에서 ...rest 를 하여 콘솔을 찍어보면 addToDo 라는 함수가 props로 들어와 있는것을 알 수 있습니다

 

import React, { useState } from 'react';
import { connect } from 'react-redux';
import { actionCreators } from 'store';

function Home({ toDos, ...rest }) {
  console.log(rest);
  const [text, setText] = useState('');
  const onChange = (e) => {
    setText(e.target.value);
  };
  const 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>{toDos}</ul>
    </>
  );
}

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

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

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

connect에서 dispatch 함수 넣었더니 컴포넌트에서 props 인자로 함수를 받은 모습

 

 

이렇게 받은 addToDo 함수를 이용했더니 잘 나왔습니다.

 

import React, { useState } from 'react';
import { connect } from 'react-redux';
import { actionCreators } from 'store';

function Home({ toDos, addToDo }) {
  const [text, setText] = useState('');
  const onChange = (e) => {
    setText(e.target.value);
  };
  const onSubmit = (e) => {
    e.preventDefault();
    const id = Date.now();
    addToDo(text, id);
    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>
    </>
  );
}

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

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

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

정상작동하는 모습입니다.

 

 

getState() 기능은 필요없고 dispatch 만 이용하고자 할 때

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

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

첫번째 인자를 null 로 하여서 dispatch만 이용하시면 됩니다.

 

 

mapStateToProps?: (state, ownProps?) => Object

mapStateTops 함수가 지정된 경우 새 래퍼 구성 요소는 Redux 저장소 업데이트를 구독합니다. 즉, 저장소가 업데이트될 때마다 mapStateTops가 호출됩니다. mapStateTops의 결과는 래핑된 구성요소의 소품으로 병합되는 일반 객체여야 합니다. 스토어 업데이트를 구독하지 않으려면 mapStateToProps 대신 null 또는 정의되지 않은 정보를 전달하십시오.

 

https://react-redux.js.org/api/connect#mapstatetoprops-state-ownprops--object

 

Connect | React Redux

API > connect: a Higher-Order Component to interact with Redux

react-redux.js.org

ownProps()

 

mapStateToProps 함수가 두 개의 매개 변수를 사용하는 것으로 선언되면 저장소 상태가 변경될 때마다 또는 래퍼 구성요소가 새 소품을 수신할 때마다 호출됩니다( 얕은 동등 비교에 기반함). 첫 번째 매개 변수로 저장소 상태가 지정되고 두 번째 매개 변수로 래퍼 구성 요소의 속성이 지정됩니다.

두 번째 매개변수는 일반적으로 규칙에 따라 ownProps라고 합니다.

 

dispatch 함수를 넘길 때 두번째 인자를 콘솔로그 해오면 저장소의 상태가 변경될 때 컴포넌트가 가지고 있는 props를 가져와 줍니다.

import React from 'react';
import { connect } from 'react-redux';

function ToDo({ text, id }) {
  return (
    <li id={id}>
      {text}
      <button>DEL</button>
    </li>
  );
}

function mapDispatchToProps(dispatch, ownProps) {
  console.log(ownProps);
}

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

저장소의 상태가 변할 때의 값을 보여줍니다.

 

import React from 'react';
import { connect } from 'react-redux';
import { actionCreators } from 'store';

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

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

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

그래서 다음과 같이 ownProps의 정보를 통해서 dispatch를 이용할 수도 있습니다.