벨로퍼트 님의 강의를 들으면서 useState에 대한 예제로 간단한 평균 계산을 하는 예제를 해보았다.
아래의 코드는 useState로 구현 한 것 이다.
import React, { useCallback, useMemo, useState, useRef } from 'react';
const getavg = (numbers) => {
if (numbers.length === 0) return 0;
const sum = numbers.reduce((acc, current) => acc + current);
return sum / numbers.length;
};
const GetAvg = () => {
const [number, setNumber] = useState('');
const [list, setList] = useState([]);
const inputEI = useRef(null);
const onChange = useCallback((e) => {
setNumber(e.target.value);
}, []);
const onClickAdd = useCallback(() => {
const nextList = list.concat(parseInt(number));
setList(nextList);
setNumber('');
inputEI.current.focus();
}, [number, list]);
const avg = useMemo(() => getavg(list), [list]);
return (
<div>
<h1>평균값 : {(console.log(avg), avg)}</h1>
<input
type="number"
placeholder="숫자입력"
value={number}
onChange={onChange}
ref={inputEI}
/>
<button onClick={onClickAdd}>추가</button>
<ul>
{list.map((value, index) => (
<li key={index}>{value}</li>
))}
</ul>
</div>
);
};
export default GetAvg;
useReducer가 useState와 동일하게 상태관리를 할 수 있다는 걸 배운 점에서 이를 useReducer로 바꾸고 싶어서 도전해 보았다.
이를 해결 해보려고 하니 여러 문제점들이 생겼다.
1. 어떤 것을 action type으로 잡아줘야지 동작을 잘 할 수 있을까?
2. useState는 가시적으로 상태 변환이 쉬운데 이를 어떻게 해결해야 하나?
3. action과 state의 기본적인 이해 부족
평균을 구하는 것은 reducer 안에서 처리하는 것 보다는 바깥쪽에서 처리하는게 좋을 것 같아서 바깥 부분에서 처리하였다.
function getAvg(numbers) {
if (numbers.length === 0) {
return 0;
}
const sum = numbers.reduce((acc, current) => acc + current);
return sum / numbers.length;
}
reducer 함수 구현
가장 문제였던 점은 state와 action에 대한 이해가 정확하지 않았어서 console로 모든 값을 찍어보면서 이를 확인해 보았다. switch 구문을 이용해서 action.type을 구분해 주었고 input DOM에 대한 내용은 별다르게 action.type을 정해줄 수 없다고 판단하여서 default로 처리 하였다.
> 이해내용 : state는 아직 바뀌지 않은 현재 상태를 의미
action은 action에 대한 행동에 대한 상태변화를 의미
function reducer(state, action) {
switch (action.type) {
case 'CLICK': {
console.log('click' + action.list);
console.log('click' + action.number);
console.log('click' + action);
console.log('click' + action.value);
console.log('click' + action.name);
return {
...state,
list: [...state.list, parseInt(state.number)],
//[state.number]: '',
//[action.number]: '',
number: '',
};
}
default:
console.log('타이핑' + state.list);
console.log('타이핑' + state.number);
console.log(state);
console.log(action);
console.log('타이핑' + action.value);
console.log('타이핑' + action.name);
return {
...state,
[action.name]: action.value, //나중에 유지 보수를 위해 input 값에 대한 name 사용하여 정의
//number: action.value,
//[state.number]: action.value,
};
}
}