관리 메뉴

CASSIE'S BLOG

[슈퍼코딩] 71강 Redux 본문

PROGRAMMING/슈퍼코딩 강의 정리

[슈퍼코딩] 71강 Redux

ITSCASSIE1107 2023. 11. 15. 22:37
반응형

React-redux

Store, Reducer 만들기

Provider로 감싸기

useSelector

컴포넌트에서 Action을 Dispatch하기

데이터를 관리하는 store

store에 변화를 주는 Reducer

이제는 React-redux라는 상태관리라이브러리를 같이 사용한데

다른 개념이 아니라 그냥 리액트에서 리덕스 쓸 수 있게 만든 개념


✅practice/5-5 checkout


 Summary

✅npm install redux react-redux 설치 

 

✅ npm start


✅ App.js 먼저 들어가면 Counter 컴포넌트 하나만 있어서 Counter 컴포넌트 들어가기 (껍데기만 있는 UI)

 

import classes from './Counter.module.css';

const Counter = () => {
  const toggleCounterHandler = () => {};

  return (
    <main className={classes.counter}>
      <h1>Redux Counter</h1>
      <div className={classes.value}>-- 카운터 값 --</div>
      <button onClick={toggleCounterHandler}>토글 카운터</button>
    </main>
  );
};

export default Counter;


카운터라는 state가 바뀌는 걸 볼 수 있도록 만들 예정 

 

✅ 가장 먼저 만들어야할 것이 Store와 Reducer다. 

 

 

 

 

✅  store 폴더 만들어주고  index.js만들어준다. (src 안에)

 

여기서 store를 관리할 예정 reducer를 같이 만들어도 됨. 
이건 간단한 어플리케이션이여서 하나의 파일에서 관리하는게 보기도 편하고 관리도 쉬움 
많은 store값들을 다루게 되고 reducer도 그에 맞게 많이 만들어주게 된다면
파일들을 분리해도 상관없다. 

 

✅ 

 

이전 강의에서 했는데 Reducer는 state값 설정하는 부분이 있고, action를 받는다고함. 


이 문장은 Redux에서 상태(state)를 다루는 리듀서(reducer) 함수를 작성할 때의 몇 가지 관례와 권장 사항을 설명하고 있습니다. 아래는 주요 내용을 정리한 것입니다:

첫 호출 시 state 값이 undefined인 경우:

리듀서 함수가 처음 호출될 때 상태 값이 undefined로 전달될 수 있습니다.
이때, 함수 파라미터에 기본 값(default value)을 설정하여 초기 상태(initialState)를 지정할 수 있습니다.
불변성 유지를 위한 spread 연산자 활용:

상태의 불변성을 유지하기 위해 데이터를 업데이트할 때 spread 연산자를 사용합니다.
Spread 연산자를 활용하면 기존 상태를 변경하지 않고 새로운 상태를 생성할 수 있습니다.
리덕스 상태를 최대한 깊지 않은 구조로 유지하는 권장:

Redux 상태는 최대한 얕은 구조로 유지하는 것이 권장됩니다.
얕은 구조로 유지하면 spread 연산자를 사용하여 불변성을 보다 쉽게 유지할 수 있습니다.
immer 라이브러리 사용 권장:

Redux에서 객체나 배열과 같은 복잡한 구조를 다룰 때, 불변성을 관리하고 업데이트하는 것이 번거로울 수 있습니다.
immer 라이브러리를 사용하면 더 쉽게 리듀서를 작성할 수 있습니다.
이러한 관례와 권장 사항을 따르면 Redux 상태를 효과적으로 관리하고 불변성을 유지하는 데 도움이 됩니다.
 
 
루트 리듀서 (rootReducer)

스토어 만들 때 (createStore 함수를 사용하여) 리듀서 1개만 사용해야 함

→ 리듀서를 1개로 합쳐야 함

createStore()쓰려면
import {createStore} from ‘redux’;

Import 해줘야함

그리고 createStore();안에 매개변수에 Reducer함수를 넣어준다.

Provider로 감싸기

리액트에서 리덕스를 사용하기
위해선 React-redux의 Provider로 <App />를 최상단에서 감싸줍니다.

그리고 사용하는 store를 이 Provider로 넘겨주어야합니다.

useSelector
리액트 리덕스 팀에서 만든 커스텀 훅
state로부터 값을 가져올 때 사용합니다.

이거 실습도하고
useSelector 레퍼런스 자료도 봐야함

shallowEqual

react-dux에 내장된 함수로서 객체안의 가장 겉에 있는 값들을 모두 비교해줍니다.

useDispatch로 가져오면 끝
const dispatch = useDispatch();

 

 

 

✅createStore일단 밑줄

 

 

 

import {createStore} from 'redux'

const counterReducer = (state = {counter : 0},){
    if(action.type === 'increment'){
        return {
            counter: state.counter + 1
        }
    }

    if(action.type === 'decrement'){
        return {
            counter: state.counter - 1
        }
    }
    return state;
}

const store = createStore(counterReducer);

export default store;

 

 

 

 

 

 

 

import React from 'react';
import ReactDOM from 'react-dom/client';
import { Provider } from "react-redux";

import './index.css';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <Provider>
        <App />
    </Provider>
);

 

 

이게 끝이 아니고 Provider에 store를 매핑해줘야한다.
그 store가 전역에서 관리하는 데이터 센터

 

✅방금 만들었던 store를 가져와서 매핑해주면 됨

 

 

import React from 'react';
import ReactDOM from 'react-dom/client';
import { Provider } from "react-redux";

import './index.css';
import App from './App';
import store from './store/index';

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

 

 

 

✅셀렉터함수 

(state) => state.counter 함수는 Redux에서 사용되는 일종의 셀렉터 함수입니다. 셀렉터 함수는 Redux 스토어의 전체 상태를 받아오고, 그 중에서 필요한 부분만을 선택하여 반환하는 함수입니다. 여기서는 counter 필드의 값을 선택하여 반환하고 있으므로 이 함수는 counter 필드에 대한 셀렉터 함수로 볼 수 있습니다. 이렇게 사용자가 필요한 상태 값만을 선택하여 가져오는 것은 불필요한 리렌더링을 방지하고 효율적으로 상태를 관리하는 데 도움이 됩니다.

 

(state) => state.counter 함수는 전체 Redux 스토어 상태를 받아오면서 그 중에서 counter 필드만을 선택하여 반환합니다. 아 이게 state를 받아서 state 중에 counter 필드만 받아온다는 말이지? 맞음.

 

state = {counter :0} 
이 {} 안에 object가 state다.

 

import { useSelector } from 'react-redux';
import classes from './Counter.module.css';

const Counter = () => {
  const toggleCounterHandler = () => {};
  const counter = useSelector((state)=>state.counter);

  return (
    <main className={classes.counter}>
      <h1>Redux Counter</h1>
      <div className={classes.value}>{counter}</div>
      <button onClick={toggleCounterHandler}>토글 카운터</button>
    </main>
  );
};

export default Counter;

 

바로 오류나서 보니 counterReducer에 화살표함수도 안 만들고, action도 안 보내줌. 

 

import {createStore} from 'redux'

const counterReducer = (state = {counter : 0}, action) => {
    if(action.type === 'increment'){
        return {
            counter: state.counter + 1
        }
    }

    if(action.type === 'decrement'){
        return {
            counter: state.counter - 1
        }
    }
    return state;
}

const store = createStore(counterReducer);

export default store;

 

✅여기서 까지는 store 가지고 온 것 까지만. 

 

 

 

 

 

✅ 버튼을 클릭하면 dispatch로 action.type이 전달되는거야 그게 Reducer로!
dispatch import 해줘야한다. 

 

before

 

import { useSelector } from 'react-redux';
import classes from './Counter.module.css';

const Counter = () => {
  const toggleCounterHandler = () => {};
  const counter = useSelector((state)=>state.counter);

  return (
    <main className={classes.counter}>
      <h1>Redux Counter</h1>
      <div className={classes.value}>{counter}</div>
      <button onClick={toggleCounterHandler}>토글 카운터</button>
    </main>
  );
};

export default Counter;

 

after

 

 

 

 

 

 

 

import { useSelector, useDispatch } from 'react-redux';
import classes from './Counter.module.css';

const Counter = () => {
  const toggleCounterHandler = () => {};
  const counter = useSelector((state)=>state.counter);
  const dispatch = useDispatch();


  const incrementHandler = () => {
    dispatch({type: "increment"});
  }

  const decrementHandler = () => {
    dispatch({type: "decrement"});
  }

  return (
    <main className={classes.counter}>
      <h1>Redux Counter</h1>
      <div className={classes.value}>{counter}</div>
      <button onClick={toggleCounterHandler}>토글 카운터</button>
      <button onClick={incrementHandler}>증감 카운터</button>
      <button onClick={decrementHandler}>감소 카운터</button>
    </main>
  );
};

export default Counter;

 

반응형