안녕하세요 제로초님.
3-11강을 수강하던중 의문이 생겼습니다.
1. 만약 try컴포넌트에 memo를 사용하게 되면 숫자를 입력할때는 부모컴포넌트인 NumberBaseball에서 onChangeInput 함수가 실행되어 value state만 변경되어서 자식컴포넌트인 try컴포넌트는 리렌더링이 되자않는것은 이해했습니다.
그러나 숫자를 입력하고 입력버튼을 눌러 onSubmitForm함수가 실행되게 되면 tries state 배열에 데이터가 추가되고 try컴포넌트에 props인 tryInfo props를 넘겨주잖아요? 이때 tries state배열이 변경되었는데 왜 자식컴포넌트인 try를 리렌더링이 되지 않는지 궁금합니다!
입력버튼을 눌렀을 때는 tries의 state가 변하고 props를 넘겨주니 자식컴포넌트인 try 컴포넌트가 한번 렌더링 되어야 하는거 아닌가요?..
밑에는 전체 코드입니다!
const NumberBaseball = () => {
const [answer, setAnswer] = useState(getNumbers());
const [value, setValue] = useState("");
const [result, setResult] = useState("");
const [tries, setTries] = useState([]);
const inputEl = useRef(null);
const onSubmitForm = useCallback(
(e) => {
e.preventDefault();
if (value === answer.join("")) {
setTries((t) => [
...t,
{
try: value,
result: "홈런!",
},
]);
setResult("홈런!");
alert("게임을 다시 실행합니다.");
setValue("");
setAnswer(getNumbers());
setTries([]);
inputEl.current.focus();
} else {
const answerArray = value.split("").map((v) => parseInt(v));
let strike = 0;
let ball = 0;
if (tries.length >= 9) {
setResult(`10번 넘게 틀려서 실패! 답은 ${answer.join(",")}였습니다!`); // state set은 비동기
alert("게임을 다시 시작합니다.");
setValue("");
setAnswer(getNumbers());
setTries([]);
inputEl.current.focus();
} else {
console.log("답은", answer.join(""));
for (let i = 0; i < 4; i += 1) {
if (answerArray[i] === answer[i]) {
console.log("strike", answerArray[i], answer[i]);
strike += 1;
} else if (answer.includes(answerArray[i])) {
console.log(
"ball",
answerArray[i],
answer.indexOf(answerArray[i])
);
ball += 1;
}
}
setTries((t) => [
...t,
{
try: value,
result: `${strike} 스트라이크, ${ball} 볼입니다.`,
},
]);
setValue("");
inputEl.current.focus();
}
}
},
[value, answer]
);
const onChangeInput = useCallback((e) => setValue(e.target.value), []);
return (
<>
<h1>{result}</h1>
<form onSubmit={onSubmitForm}>
<input
ref={inputEl}
maxLength={4}
value={value}
onChange={onChangeInput}
/>
<button>입력!</button>
</form>
<div>시도: {tries.length}</div>
<ul>
{tries.map((v, i) => (
<Try key={`${i + 1}차 시도 : ${v.try}`} tryInfo={v} />
))}
</ul>
</>
);
};
export default NumberBaseball;
try.js
import React, { memo } from 'react';
const Try = memo(({tryInfo}) => {
return (
<li>
<div>{tryInfo.try}</div>
<div>{tryInfo.result}</div>
</li>
);
});
export default Try;
아... 제가 잘못이해한것 같습니다.
그러면 tries state에 배열에 객체가 하나 추가 혹은 제거 되더라도 state가 추가 혹은 제거되는 것일 뿐 tries state가 변경되는 것은 아니어서 리렌더링이 일어나지 않는다는 말씀이시죠? (Memo도 사용했기 때문)
제가 이해한게 맞나요?...