react-redux

nn·2022년 6월 18일
0

react-redux(2022 개정판) 을 듣고 정리한 내용입니다.

react-redux

react-redux 란 redux를 react에서 쉽게 사용할 수 있도록 돕는 도구이다.


props

컴포넌트 간에 데이터를 주고 받을 때 사용하는 것이 props이다.

import React, { useState } from 'react';
import './style.css';

export default function App() {
  const [number, setNumber] = useState(1);
  return (
    <div id="container">
      <h1>Root : {number}</h1>
      <div id="grid">
        <Left1 number={number}></Left1>
       
      </div>
    </div>
  );
}
function Left1(props) {
  return (
    <div>
      <h1>Left1 : {props.number}</h1>
      <Left2 number={props.number}></Left2>
    </div>
  );
}
function Left2(props) {
  return (
    <div>
      <h1>Left2 : {props.number}</h1>
      <Left3 number={props.number}></Left3>
    </div>
  );
}
function Left3(props) {
  return (
    <div>
      <h1>Left3 : {props.number}</h1>
    </div>
  );
}

위 예시는 3개의 컨테이너가 중첩되어있다.
실행을 하면 다음과 같은 화면이 나온다.

Root에서 Left3까지 number를 전달하기 위해선 중첩된 컨테이너에 모두 props 전달해 주어야함 하위 컴포넌트까지 데이터를 전달할 수 있게 된다.


중첩된 컴포넌트가 수십, 수백개가 되는 경우엔 어떻게 해야할까?
수십, 수백개의 컴포넌트를 모두 props로 연결하지 않고도 컴포넌트에 데이터를 전달하는 방법을 알아보자.


redux 설치

npm install redux react-redux

위 명령어를 이용하여 reduxreact-redux를 설치하자.


createStore

store는 데이터를 저장하고 있는 공간이다.
이 공간을 만들기 위해 redux에서 createStore를 만들어 주자.
store불변상태로 저장되어야 하므로 const로 사용해 상수로서 선언하였다.

import { createStore } from 'redux';
const store = createStore(reducer);

reducer

reducer는 데이터의 상태 변화를 전달해준다.
store와 연결하여 변경된 상태를 저장한다.

reducer는 현재상태와, 어떻게 바꿀 것인지 요청을 받는 두개의 파라메터를 인자로 받는다.

function reducer(currentState, action) {
  // 현재 상태가 정의 되지 않았다면
  // 기본 상태값을 리턴
  if (currentState === undefined) {
    return {
      number: 1,
    };
  }

currentState가 정의되어있지 않는 경우에 기본값을 현재 상태로 지정해주었다.


Provider

import { Provider, useSelector, useDispatch, connect } from 'react-redux';

Providerreact-redux에서 임포트해서 사용하는 4가지 항목 중 하나로써, 상태 데이터를 어떤 컴포넌트에게 전달할지 지정해주는 컴포넌트이다.

export default function App() {
  return (
    <div id="container">
      <h1>Root </h1>
      <div id="grid">
        {/* Provider는 store이라는 props를 반드시 전달해주어야한다.  */}
        <Provider store={store}>
          <Left1></Left1>
        </Provider>
      </div>
    </div>
  );
}

Left1 컴포넌트를 Provider로 감싼 후, store를 전달해 주자.
reducercurrentState가 정의되지 않았으므로 기본 값인 1이 number에 저장된다.


useSelector

useSelector는 상태를 전달 받고 싶을 곳에서 사용한다.

props를 통해 Left1, Left2를 거치지 않고 직접 Left3에게 직접 전달해 줄 것이므로 다음과 같이 Left3 컴포넌트를 수정하자.

function Left3(props) {
  // number 값을 직접 전달받고 싶을때
  // useSelector는 함수를 인자로 받는다.
  const number = useSelector((state) => state.number);
  return (
    <div>
      <h1>Left3 : {number} </h1>
    </div>
  );
}

useDispatch

useDispatch는 상태 값을 변경할 때 사용한다.
Left3에 버튼을 만들고, 버튼을 클릭할때마다 number가 하나씩 증가하도록 해보자.

function Left3(props) {
  // number 값을 무선으로 전달받고 싶을때
  // useSelector는 함수를 인자로 받는다.

  const number = useSelector((state) => state.number);
  // 상태값 변경 
  const dispatch = useDispatch();
  return (
    <div>
      <h1>Left3 : {number} </h1>
      <input
        type="button"
        value="+"
        onClick={() => {
          dispatch({ type: 'PLUS' });
        }}
      ></input>
    </div>
  );
}

onClick이 이루어 질때마다 dispatchstorereducer에게 action을 전달해 준다.

reducer함수를 수정해보자.

function reducer(currentState, action) {
  // 현재 상태가 정의 되지 않았다면
  // 기본 상태값을 리턴
  if (currentState === undefined) {
    return {
      number: 1,
    };
  }
  // state 의 변화를 불변하게 유지하기 위해 복제
  // 복제본을 수정
  const newState = { ...currentState };
  if (action.type === 'PLUS') {
    newState.number++;
  }
  return newState;
}

상태를 변경하기 위해서는 깊은 복사가 이루어져야한다.
현재 상태를 복제하고 복제본을 수정하여 리턴하면 상태가 변경된다.


전체 코드

import React, { useState } from 'react';
import './style.css';
import { createStore } from 'redux';
// 4인방
// 컴포넌트, 어떤스테이트를 사용할지 선택할때, 스테이트 값을 변경
import { Provider, useSelector, useDispatch, connect } from 'react-redux';
function reducer(currentState, action) {
  // 현재 상태가 정의 되지 않았다면
  // 기본 상태값을 리턴
  if (currentState === undefined) {
    return {
      number: 1,
    };
  }
  // state 의 변화를 불변하게 유지하기 위해 복제
  // 복제본을 수정
  const newState = { ...currentState };
  if (action.type === 'PLUS') {
    newState.number++;
  }
  return newState;
}
const store = createStore(reducer);
export default function App() {
  return (
    <div id="container">
      <h1>Root </h1>
      <div id="grid">
        {/* Provider는 store이라는 props를 반드시 전달해주어야한다.  */}
        <Provider store={store}>
          <Left1></Left1>
        </Provider>
      </div>
    </div>
  );
}
function Left1(props) {
  return (
    <div>
      <h1>Left1 : </h1>
      <Left2></Left2>
    </div>
  );
}
function Left2(props) {
  return (
    <div>
      <h1>Left2 : </h1>
      <Left3></Left3>
    </div>
  );
}
function Left3(props) {
  // number 값을 무선으로 전달받고 싶을때
  // useSelector는 함수를 인자로 받는다.

  const number = useSelector((state) => state.number);
  const dispatch = useDispatch();
  return (
    <div>
      <h1>Left3 : {number} </h1>
      <input
        type="button"
        value="+"
        onClick={() => {
          dispatch({ type: 'PLUS' });
        }}
      ></input>
    </div>
  );
}
profile
내가 될 거라고 했잖아

0개의 댓글