React

Redux 사용법

차돌박이츄베릅 2023. 6. 21. 12:24

1. 모듈 만들기

(src/redux/modules/counter.js)

// 초기 상태값(state)
const initialState = {
    number: 0,
};

// 리듀서 : state에 변화를 일으키는 함수
// (1) state를 action의 type에 따라 변경하는 함수

// input : state와 action 이 두가지를 받음
// action은 객체 형태로 되어있고 type과 value을 가지고 있음
// state를 어떻게 수정할건지 action에 대해 표현하는게 action 객체
const counter = (state = initialState, action) => {
    switch (action.type) {
        default:
            return state;
    }
};
// 만든 counter리듀서를 configStore.js의 rootReducer에 import해서 넣어주면 애플리케이션 전체에서 counter라는 reducer를 쓸 수 있는 상황이 됨

// 내보내기
export default counter;

 


2. 모듈을 스토어에 연결하기

(src/redux/config/configStore.js)

// 중앙 데이터 관리소(store)를 설정하는 부분
import { createStore } from 'redux'; // store를 만드는 API
import { combineReducers } from 'redux'; // reducer들을 하나로 묶는 역할을 하는 API
import counter from '../modules/couter'; // counter라는 리듀서를 임포트
import users from '../modules/users';

// 인자로 객체 형태
// counter라는 리듀서를 key: value형태로 넣어주면 됨. counter: counter인데 key value가 같은경우 생략이 가능해서 counter
const rootReducer = combineReducers({
    counter,
    users: users,
});

// reducer의 묶음들이 인자로 들어가야 함. 즉, rootReducer
const store = createStore(rootReducer);

// store를 사용해서 application에 주입하는 단계가 필요
export default store;

 

 

3. 스토어 조회하기

(App.jsx)

import logo from './logo.svg';
import './App.css';
import { useSelector } from 'react-redux';

function App() {
    // redux Hook
    // 여기에서 store에 접근하여, counter의 값을 읽어오고 싶다!
    // useSelector
    // 매개변수로 콜백함수
    // 현재 state전체를 가지고 있음. 중앙 저장소 state 전체
    // const data = useSelector((state) => {
    //     return state;
    // });
    const counter = useSelector((state) => {
        return state.counter;
    });

    return <div className="App"></div>;
}

export default App;

 


4. 스토어에 있는 State 수정하기

4-1. 리듀서가 액션객체를 받아 상태를 변경하는 코드 작성하기

(src/redux/modules/counter.js)

...
const counter = (state = initialState, action) => {
    switch (action.type) {
        case 'PLUS_ONE':
            return {
                number: state.number + 1,
            };
        case 'MINUS_ONE':
            return {
                number: state.number - 1,
            };
        default:
            return state;
    }
};
export default counter;

 

 

4-2. 리듀서에게 액션객체 보내고, 변경된 state 값 확인

(App.jsx)

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

const App = () => {
    const dispatch = useDispatch(); // dispatch 생성
    
    const number = useSelector((state) => state.counter.number
    console.log(number);
    
    return (
        <>
            <div className="App">현재 카운트 : {number}</div>
            <button
                onClick={() => {
                    // dispatch: action객체를 store에 던져주는 역할
                    // 인자로 action객체를 넣어줘야 함
                    // 객체에 type과 payload가 있는데 type만 넣어주자
                    dispatch({
                        type: 'PLUS_ONE',
                    });
                }}
            >
                +
            </button>
            <button
                onClick={() => {
                    dispatch({
                        type: 'MINUS_ONE',
                    });
                }}
            >
                -
            </button>
        </>
    );
};

export default App;

 

 

 

5. 액션객체에 Redux Payload로 값을 담아 리듀서에게 전달하기

State를 변경하는데 있어 만약 리듀서에게 어떤 값을 같이 보내줘야 한다면 payload를 액션객체에 같이 담아 보낸다.

인자로 전달한 값을 payload로 꺼내서 사용함.

(src/redux/modules/counter.js)

const PLUS_N = 'counter/PLUS_N';

// 액션 객체에 payload 추가
export const plusN = (payload) => {
    return {
        type: PLUS_N,
        payload: payload,
    };
};
...
const counter = (state = initialState, action) => {
    switch (action.type) {
        ...
        case PLUS_N:
            return {
                number: state.number + action.payload,
            };
        ...


(App.jsx)

import { useDispatch, useSelector } from 'react-redux';
import { plusN } from './redux/modules/couter';
import { useState } from 'react';

function App() {
    const [number, setNumber] = useState(0);

    // dispatch를 가져오는 방법
    const dispatch = useDispatch();

    return (
        <>
            <div className="App">현재 카운트 : {counter.number}</div>
            <div>
                <input
                    type="number"
                    value={number}
                    onChange={(event) => {
                        // +만 붙여주면 문자열로 들어온 값을 숫자로 형 변환을 해 줌
                        setNumber(+event.target.value);

                        // 구조분해할당 연습
                        // const {value} = event.target;
                    }}
                />
            </div>
            <button
                onClick={() => {
                    // dispatch: action객체를 store에 던져주는 역할
                    // 인자로 action객체를 넣어줘야 함
                    // 객체에 type과 payload가 있는데 type만 넣어주자

                    // dispatch({
                    //     type: PLUS_ONE,
                    // });

                    // 리팩토링
                    // dispatch(plusOne());

                    // payload 사용
                    dispatch(plusN(number));
                }}
            >
                +
            </button>
            <button
                onClick={() => {
                    dispatch({
                        type: 'MINUS_ONE',
                    });
                }}
            >
                -
            </button>
        </>
    );
}

export default App;


            


리덕스의 흐름

  1. dispatch가 action객체(type, payload를 갖고있음)를 store에 던진다.
    dispatch 역할: UI컴포넌트에서 어떤 action을 가지고 store로 던져주는 역할. 즉 중앙데이터관리소에 데이터를 어떻게 해달라고 action을 던져주는 놈임
  2. store는 action의 type에 따라 state를 변경.
    그럼 이 action의 타입에 따라서 reducer가 state를 제어

'React' 카테고리의 다른 글

React Router Dom  (0) 2023.06.21
Redux 리팩토링 - action creators, action values, Ducks 패턴  (0) 2023.06.21
Redux 셋팅  (0) 2023.06.21
DOM과 Virtual DOM  (0) 2023.06.21
최적화 - React.memo, useCallback, useMemo  (0) 2023.06.20