๐redux๋ฅผ ์ด์ฉํด ๋ง๋ ๊ณ์ฐ๊ธฐ ๊ธฐ๋ฅ
import React from "react";
import { createStore } from "redux";
import { Provider, useDispatch, useSelector } from "react-redux";
// Actions
const ADD_NUMBER = "ADD_NUMBER";
const ADD_OPERATOR = "ADD_OPERATOR";
const CALCULATE_RESULT = "CALCULATE_RESULT";
const CLEAR_DISPLAY = "CLEAR_DISPLAY";
const addNumber = (number) => ({ type: ADD_NUMBER, payload: { number } });
const addOperator = (operator) => ({
type: ADD_OPERATOR,
payload: { operator },
});
const calculateResult = () => ({ type: CALCULATE_RESULT });
const clearDisplay = () => ({ type: CLEAR_DISPLAY });
// Reducer
const calculatorReducer = (
state = { displayValue: "", operator: null, prevValue: null },
action
) => {
switch (action.type) {
case ADD_NUMBER:
return {
//๊ฐ์ฒด ์ ๊ฐ ์ฐ์ฐ์(...state)๋ฅผ ์ฌ์ฉํ์ฌ ํ์ฌ ์ํ๋ฅผ ๋ณต์ฌํฉ๋๋ค.
// ๋ถ๋ณ์ฑ์ ์ ์งํ๋ฉด์ ์๋ก์ด ์ํ๋ฅผ ์์ฑํ๋ ๊ธฐ๋ณธ์ ์ธ ๋ฐฉ๋ฒ์
๋๋ค.
...state,
displayValue:
state.displayValue === ""
? action.payload.number
: state.displayValue + action.payload.number,
};
case ADD_OPERATOR:
return {
...state,
operator: action.payload.operator,
prevValue: state.displayValue,
displayValue: "0",
};
case CALCULATE_RESULT:
const prev = parseFloat(state.prevValue);
const current = parseFloat(state.displayValue);
let result;
switch (state.operator) {
case "+":
result = prev + current;
break;
case "-":
result = prev - current;
break;
case "×":
result = prev * current;
break;
case "÷":
result = prev / current;
break;
case "%":
result = (prev / 100) * current;
break;
default:
result = current;
}
return {
...state,
displayValue: result.toString(),
operator: null,
prevValue: null,
};
case CLEAR_DISPLAY:
return {
displayValue: "",
operator: null,
prevValue: null,
};
default:
return state;
}
};
// Store
const store = createStore(calculatorReducer);
// App Component
const App = () => {
const displayValue = useSelector((state) => state.displayValue);
const dispatch = useDispatch();
const handleNumberClick = (number) => {
dispatch(addNumber(number));
};
const handleOperatorClick = (operator) => {
dispatch(addOperator(operator));
};
const handleEqualClick = () => {
dispatch(calculateResult());
};
const handleClearClick = () => {
dispatch(clearDisplay());
};
return (
<div>
<div>Display: {displayValue}</div>
{[1, 2, 3, 4, 5, 6, 7, 8, 9].map((number) => (
<button
key={number}
onClick={() => handleNumberClick(number.toString())}
>
{number}
</button>
))}
{["+", "-", "×", "÷", "%"].map((operator) => (
<button key={operator} onClick={() => handleOperatorClick(operator)}>
{operator}
</button>
))}
<button onClick={handleEqualClick}>=</button>
<button onClick={handleClearClick}>Clear</button>
</div>
);
};
// Render
const CalculatorApp = () => (
<Provider store={store}>
<App />
<p className="text-blue-500 text-xl font-bold">tailwindcss ํ
์คํธํ๊ณ ์์ต๋๋ค.</p>
</Provider>
);
export default CalculatorApp;
- ๋ฆฌ๋์(Reducer):
- calculatorReducer๋ ํ์ฌ ์ํ(state)๋ฅผ ๋ฐ์์ ์ก์ ์ ๋ฐ๋ผ ์๋ก์ด ์ํ๋ฅผ ๋ฐํํ๋ ํจ์์ด๋ค.
- ๊ฐ๊ฐ์ ์ก์ ํ์ ์ ๋ํ ์ํ ๋ณํ ๋ก์ง์ด ๊ตฌํ๋์๋ค.
- ์ก์
(Action): ์ก์
๊ฐ์ฒด๋ type๊ณผ payload๋ผ๋ ๋ ์์ฑ์ ๊ฐ์ง๊ณ ์๋ค.
- type: ์ก์ ์ ์ข ๋ฅ๋ฅผ ์๋ณํ๋ ๋ฌธ์์ด.
- payload: ์ก์ ๊ณผ ๊ด๋ จ๋ ๋ฐ์ดํฐ๋ฅผ ํฌํจํ๋ ๊ฐ์ฒด.
- ์คํ ์ด(Store):
- createStore ํจ์๋ฅผ ์ฌ์ฉํ์ฌ Redux ์คํ ์ด๋ฅผ ์์ฑํ๊ณ , ๊ทธ ์์ ๋ฆฌ๋์๋ฅผ ๋ฑ๋กํ๋ค.
- ์ปดํฌ๋ํธ(Component):
- App ์ปดํฌ๋ํธ์์๋ Redux์ useSelector ํ ์ ์ฌ์ฉํ์ฌ ํ์ฌ ์ํ๋ฅผ ๊ฐ์ ธ์ค๊ณ , useDispatch ํ ์ ์ฌ์ฉํ์ฌ ์ก์ ์ ๋์คํจ์นํ๋ค.
- ๋ฒํผ ํด๋ฆญ ์ด๋ฒคํธ์ ๋ฐ๋ผ ์ก์ ์ ๋์คํจ์นํ๋๋ก ํ๋ ํธ๋ค๋ฌ ํจ์๋ค์ด ์ ์๋์ด ์๋ค.
๐calculatorReducer() ํจ์ ํํค์น๊ธฐ
case ADD_OPERATOR:
return {
...state,
operator: action.payload.operator,
prevValue: state.displayValue,
displayValue: "",
};
case ADD_OPERATOR::
- switch ๋ฌธ์์ ADD_OPERATOR ์ก์ ํ์ ์ ๋ํ ์ฒ๋ฆฌ๋ฅผ ์์ํ๋ค.
...state:
- ๊ฐ์ฒด ์ ๊ฐ ์ฐ์ฐ์(...state)๋ฅผ ์ฌ์ฉํ์ฌ ํ์ฌ ์ํ๋ฅผ ๋ณต์ฌ. ์ด๊ฒ์ด ๋ถ๋ณ์ฑ์ ์ ์งํ๋ฉด์ ์๋ก์ด ์ํ๋ฅผ ์์ฑํ๋ ๊ธฐ๋ณธ์ ์ธ ๋ฐฉ๋ฒ์ด๋ค
operator: action.payload.operator:
- ์๋ก์ด ์ํ์์ operator ์์ฑ์ ์ ๋ฐ์ดํธํ๋ค. ์ด ๊ฐ์ ์ก์ ๊ฐ์ฒด์ payload์์ ์ ๋ฌ๋ ์ฐ์ฐ์ ๊ฐ์ผ๋ก ์ค์ ๋์๋ค.
prevValue: state.displayValue:
- prevValue ์์ฑ์ ํ์ฌ displayValue๋ก ์ ๋ฐ์ดํธํ๋ค. ์ด๋ ๊ฒ ํจ์ผ๋ก์จ ํ์ฌ๊น์ง์ ์ ๋ ฅ ๊ฐ์ ์ด์ ๊ฐ์ผ๋ก ์ ์ฅ.
displayValue: "":
- displayValue๋ฅผ ""์ผ๋ก ์ด๊ธฐํ. ์ฐ์ฐ์๋ฅผ ์ ๋ ฅ๋ฐ์ผ๋ฉด ์๋ก์ด ์ซ์๋ฅผ ์ ๋ ฅ๋ฐ๊ธฐ ์์ํ ๊ฒ์ด๋ฏ๋ก, ""์ผ๋ก ์ด๊ธฐํํ๋ค.
๊ฒฐ๊ณผ:
- ์๋ฅผ ๋ค์ด, ํ์ฌ state๊ฐ ๋ค์๊ณผ ๊ฐ๋ค๊ณ ๊ฐ์ ํด๋ณด์.
{
displayValue: "123",
operator: null,
prevValue: null
}
์ฌ์ฉ์๊ฐ "+" ์ฐ์ฐ์๋ฅผ ์ ๋ ฅํ๋ฉด, ์๋ก์ด ์ํ๋ ๋ค์๊ณผ ๊ฐ์ด ๋๋ค.
{
displayValue: "",
operator: "+",
prevValue: "123"
}
์ด์ displayValue๋ ""์ผ๋ก ์ด๊ธฐํ๋์๊ณ , prevValue์๋ ์ด์ ์ ์ ๋ ฅ๋ ์ซ์ "123"์ด ์ ์ฅ๋์์ต๋๋ค.
case CALCULATE_RESULT:
const prev = parseFloat(state.prevValue);
const current = parseFloat(state.displayValue);
let result;
switch (state.operator) {
case "+":
result = prev + current;
break;
case "-":
result = prev - current;
break;
case "×":
result = prev * current;
break;
case "÷":
result = prev / current;
break;
case "%":
result = (prev / 100) * current;
break;
default:
result = current;
}
return {
...state,
displayValue: result.toString(),
operator: null,
prevValue: null,
};
displayValue: result.toString()
JavaScript์์ ์ฐ์ฐ ๊ฒฐ๊ณผ๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ซ์์ด์ง๋ง, displayValue๋ ๋ฌธ์์ด ํํ๋ก ์ํ๋ก ์ ์ง๋๊ณ ์๋ค. ๋ฐ๋ผ์ displayValue์ ๋ฌธ์์ด์ ํ ๋นํ์ฌ ํ๋ฉด์ ํ์ํ๊ธฐ ์ํด result๋ฅผ ๋ฌธ์์ด๋ก ๋ณํํ๋ค.
๐์์ฌ์ด ์
์ฐ์ฐ์๋ฅผ ๋๋ ์ ๋ ์ฐ์ฐ์๊ฐ ์ถ๋ ฅ๋๋ ๊ฒ์ด ์๋๋ผ ๋น๊ฐ์ด ๋๋ค.
์ด ์ฝ๋๋ฅผ const prev = parseFloat(state.prevValue); ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ์ด์ ๊ฐ์ ์ฐ์ฐ์๊ฐ ๋ค์ด๊ฐ๋ฉด NaN ์๋ฌ๊ฐ ๋๋ค. .
'Frontend > React' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
react - Hooks(useState, useEffect, useContext) (0) | 2024.02.15 |
---|---|
react - recoil์ด๋? (0) | 2023.12.31 |
react - redux (0) | 2023.12.24 |
react - useRef ์ฌ์ฉํ๊ธฐ (0) | 2023.12.19 |
react Lifecycle , useEffect ์์ addEventListener (0) | 2023.11.17 |