2차 공부/TIL

24.07.02 redux로 counter기능 구현하기

공대탈출 2024. 7. 2. 16:55
//App.js
<div>
    <input type="number"/>
    <button>더하기</button>
    <button>빼기</button>
</div>

먼저 App.js를 다음과 같이 설정한다.


input에 숫자를 입력하고 더하기 버튼을 누르면 더해지고, 빼기버튼을 누르면 빼지는 기능을 구현할 것이다.

// src/App.js

import React, { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { addNumber } from './redux/modules/counter';

const App = () => {
    const dispatch = useDispatch();
    const [number, setNumber] = useState(0);
    //store에서 state의 counter모듈에서 number로 저장된 값을 globalNumber변수에 저장한다.
    const globalNumber = useSelector((state) => state.counter.number);
    //input값을 number state에 저장하는 onChangeHandler
    const onChangeHandler = (e) => {
    	//value를 구조분해할당으로 꺼내어 쓴다. 기존엔 e.target.value로 썼음
        const { value } = e.target;
        setNumber(+value);
    };
    //더하기 버튼 Click 핸들러
    //addNumber action Creator에 number을 인자로 넣어 dispatch해준다.
    const onClickAddNumberHandler = () => {
        dispatch(addNumber(number));
    };
    return (
        <div>
            {globalNumber}
            <input type="number" onChange={onChangeHandler} />
            <button onClick={onClickAddNumberHandler}>더하기</button>
            <button>빼기</button>
        </div>
    );
};

export default App;

 

// src/modules/counter.js

//Action Value
const ADD_NUMBER = 'ADD_NUMBER';
//Action Creator
//addNumber이라는 action creator을 만들어주고 export하여 다른 곳에서도 사용한다.
export const addNumber = (payload) => {
    return {
        type: ADD_NUMBER,
        payload: payload,
    };
};
//Initial State
const initialState = {
    number: 0,
};
//Reducer
//counter리듀서에 state와 action이 인자로 들어온다. 
//실제로 보내주는 값은 action이다. state는 저장된 값에서 가져옴
const counter = (state = initialState, action) => {
    switch (action.type) {
    	//action.type가 ADD_NUMBER일 때 
        case ADD_NUMBER: {
            return {
            	//state의 number에 기존값과 payload로 전해져 온 값을 더해 저장한다.
                number: state.number + action.payload,
            };
        }
        default:
            return state;
    }
};
//export default reducer
export default counter;

 

버튼을 클릭하면 onClickAddNumberHandler가 작동한다.

이 함수는 addNumber라는 actionCreator에 input에 적혀있는 number라는 state를 담아서 dispatch해준다.

const onClickAddNumberHandler = () => {
        dispatch(addNumber(number));
    };
<div>
    {globalNumber}
    <input type="number" onChange={onChangeHandler} />
    <button onClick={onClickAddNumberHandler}>더하기</button>
    <button>빼기</button>
</div>

 

addNumber action creator은 다음과 같다.

인자로 payload값(input에 입력한 값)을 받고 type을 ADD_NUMBER, payload를 payload로 return해주는 함수이다.

이 값은 리듀서로 가게된다.

action의 type가 ADD_NUMBER인 케이스가 실행되는데 해당 케이스는 기존 state에 저장되어있는 number와 payload로 넘어온 값을 더해 number에 다시 저장하는 것이다.

state값이 변하고, App.js에 useSelector로 가져온 globalNumber가 변하게 되면서 리렌더링이 일어나게 된다.

// src/modules/counter.js

//Action Value
const ADD_NUMBER = 'ADD_NUMBER';
//Action Creator
export const addNumber = (payload) => {
    return {
        type: ADD_NUMBER,
        payload: payload,
    };
};
//Initial State
const initialState = {
    number: 0,
};
//Reducer
const counter = (state = initialState, action) => {
    switch (action.type) {
        case ADD_NUMBER: {
            return {
                number: state.number + action.payload,
            };
        }
        default:
            return state;
    }
};
//export default reducer
export default counter;

 

빼기 기능도 더하기 기능과 같게 작성하되, case에서 state.number - action.payload만 해주면 된다.


최종 코드

// src/App.js

import React, { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { addNumber, substractNumber } from './redux/modules/counter';

const App = () => {
    const dispatch = useDispatch();
    const [number, setNumber] = useState(0);
    const globalNumber = useSelector((state) => state.counter.number);
    const onChangeHandler = (e) => {
        const { value } = e.target;
        setNumber(+value);
    };
    const onClickAddNumberHandler = () => {
        dispatch(addNumber(number));
    };
    const onClickSubstractNumberHandler = () => {
        dispatch(substractNumber(number));
    };
    return (
        <div>
            {globalNumber}
            <input type="number" onChange={onChangeHandler} />
            <button onClick={onClickAddNumberHandler}>더하기</button>
            <button onClick={onClickSubstractNumberHandler}>빼기</button>
        </div>
    );
};

export default App;
// src/modules/counter.js

//Action Value
const ADD_NUMBER = 'ADD_NUMBER';
const SUBSTRACT_NUMBER = 'SUBSTRACT_NUMBER';
//Action Creator
export const addNumber = (payload) => {
    return {
        type: ADD_NUMBER,
        payload: payload,
    };
};
export const substractNumber = (payload) => {
    return {
        type: SUBSTRACT_NUMBER,
        payload: payload,
    };
};
//Initial State
const initialState = {
    number: 0,
};
//Reducer
const counter = (state = initialState, action) => {
    switch (action.type) {
        case ADD_NUMBER: {
            return {
                number: state.number + action.payload,
            };
        }
        case SUBSTRACT_NUMBER: {
            return {
                number: state.number - action.payload,
            };
        }
        default:
            return state;
    }
};
//export default reducer
export default counter;