REACT (09.25) - 상위, 하위 컴포넌트, 구조분해할당, setState
const App = () => {
const [todos, setTodos] = useState([]);
// setTodos([...todos, todos.length + 1]); 요청함수 오버
setTimeout(function () {
console.log("실행됨!:);
}, 5000); // setInterval과 다르게 한번만 실행되고 끝남
return (
<>
<div></div>
<hr />
<div>{JSON.stringify(todos)}</div>
</>
);
};
위 코드에서 setTodos([...todos, todos.length + 1]); 가 문제를 발생하는 이유는 함수 컴포넌트의 랜더링 함수 내에서 직접 실행되기 때문.
useState 함수인 setTodos를 컴포넌트의 본문 안에서 직접 호출하면 무한 루프에 빠지게 됨 -> 업데이트될 때마다 해당 컴포넌트가 다시 렌더링되기 때문
그로 인해서 setTodos가 호출이되고, 이 과정이 계속 반복되어 무한 루프에 빠지게 되는 것이다.
setInterval(function () {
setTodos([...todos, todos.length + 1]);
console.log("실행됨!");
}, 5000);
위 코드를 작성하면

개발자 관리창에 사진처럼 순차적으로 올라가지않고, 무작위로 올라가는 모습을 볼 수 있는데 이도 useState 함수를 사용해서 무한 루프에 빠진 상태로 보면 된다.
이때 setTimeout을 사용하게 되면 순차적으로 올라가는 것 확인 가능!
(App이 랜더링 된 후 5초 뒤에 코드 한번 실행)
React 함수와 데이터
컴포넌트 상태관리 용이하도록, 효율적인 리렌더링을 위해서 함수와 데이터는 최대한 하위 컴포넌트에서 생성, 필요한 것만 상위 컴포넌트에서 생성하는 것이 좋다.
- 상위 컴포넌트 (APP)
- 전체 트리 구조의 최상단에 위치하여 하위 컴포넌트에게 데이터(함수)를 전달(공급, 제공)한다. 만약 상위 컴포넌트에서 불필요하게 많은 데이터를 생성하고 관리한다면, 리렌더링 시 상위 컴포넌트의 모든 하위 컴포넌트가 불필요하게 리렌더링될 수 있다.
- 하위 컴포넌트 (todoWrite)
- 상위에서 받은 데이터를 소비(사용)하고, 가능한 경우 직접 데이터를 생성하고 관리하는 것이 좋다. 이렇게 하면 변수와 함수의 스코프(사용처)를 하위 컴포넌트에서 한정할 수 있고, 상위 컴포넌트의 리렌더링 영향을 줄일 수 있다.
효율적인 리렌더링을 위해 상위 컴포넌트에서 필요한 최소한의 데이터만 관리하고, 나머지 로직이나 상태는 하위 컴포넌트에서 처리한다. 이를 통해서 리렌더링의 범위를 최소화하고, 성능을 향상시킬 수 있다.
구조분해할당
새로운 변수 이름으로 할당
const TodoWriteForm = ({ addTodo: _addTodo })
const TodoWriteForm = ({ addTodo: qqqqqq })
이름 지정해서 사용 가능하며, 보통 _로 붙여서 사용한다.
이전까지 setTodos 함수를 하위 컴포넌트에 직접 전달하여 사용하였는데, 이렇게 되면, 하위 컴포넌트가 상위 컴포넌트의 상태를 직접적으로 변경할 수 있기에 적절하지 않다.
따라서 set이 아니라 removTodo를 최상위 컴포넌트인 App에 위치시키고 removeTodo를 현재 최하위 컴포넌트인 TodoListItem에서 사용할 수 있도록 인자로 넘겨준다. 이렇게 되면 하위 컴포넌트에서는 해당 기능 (remove)을 호출만 하게 되고, 주요 상태 변경은 상위 컴포넌트가 처리하게 된다.
하위 컴포넌트는 데이터 변경 로직에 의존하지 않고, 필요한 기능만 수행할 수 있도록 하는 것이 좋다.
setState
- setState 함수는 비동기적으로 동작하기 때문에, 상태가 즉시 업데이트되지 않는다.
const onClick = () => {
setNumber(number + 1);
console.log(`number : ${number}`);
}
- setState를 호출하면 상태가 바로 변경되지 않는다. 이벤트 함수가 실행될 때 setState는 상태 변경을 예약해 놓는다. 하지만 이벤트 함수가 종료되기 전에는 상태가 아직 반영되지 않기 때문에, console에 출력된 값은 업데이트 이전의 상태를 나타나게 되고, setState 호출 직후와 렌더링 완료 시점 간에 차이가 생긴다.