리액트에서 "children"이란 무엇일까?
children은 prop일 뿐이다.
const Parent = ({ children }) => {
return <>{children}</>;
};
즉 아래의 코드 (1), (2)는 같다.
// (1)
<Parent children={<Child />} />
// (2)
<Parent>
<Child />
</Parent>
그렇다면 Element를 prop으로 넘긴다는 것은 어떤 뜻일까?
아래의 두 코드는 같은 뜻이다. 모두 리액트 element를 생성, 할당하고 있다.
const children = <Child />
const children = React.createElement(Child, null, null);
element가 변경되면 위와 같은 재생성 및 재할당과정이 일어난다.
그렇다면 리액트 element란 무엇인가? 바로 아래와 같은 객체일 뿐이다.
{
type: Child,
props: null,
key: null,
ref: null,
}
이제 아래 의문들을 풀어보며 children props를 이해해보자.
1. children이 리렌더링 되지 않는다?
const MovingComponent = ({ children }) => {
const [state, setState] = useState({ x: 100, y: 100 });
return (
<div onMouseMove={(e) => setState({ x: e.clientX - 20, y: e.clientY - 20 })}>
{children}
</div>
);
};
- 위와 같은 컴포넌트의 state가 바뀌어도, children은 리렌더링 되지 않는다.
- 그 이유는, 넘겨진 children은 단순한 객체일 뿐이고, 재생성되지 않기 때문이다.
2. children을 감싼 컴포넌트에서는 React.memo가 작동하지 않는다?
const MovingComponentMemo = React.memo(MovingComponent);
const SomeOutsideComponent = () => {
const [state, setState] = useState();
return (
<MovingComponentMemo>
<ChildComponent />
</MovingComponentMemo>
)
}
- ChildComponent를 감싼 MovingComponentMemo 컴포넌트는, ChildComponent라는 객체를 prop으로 받는 컴포넌트이다.
- 즉 SomeOutsideComponent 가 리렌더링되면, return이 실행되면서, 객체 ChildComponent가 재생성된다.
- 객체가 재생성되며 참조값이 바뀌었기 때문에, MovingComponentMemo가 메모이제이션 되었더라도 리렌더링된다.
- ChildComponent 역시 리렌더링된다.
그래서 이건 왜그런거라고?
- children은 이미 생성된 객체로 넘어갔기 때문에 부모 컴포넌트가 리렌더링되어도 리렌더링되지 않는다.
- 즉 CounterProvider 의 자식들은 모두 리렌더링 되지 않아야 한다.
- 그런데 useContext의 규칙(자동으로 context를 쓰는 자식 컴포넌트를 리렌더링한다) 때문에 해당 context가 사용되고 있는 MyComponent3, MyComponent4, MyButton 컴포넌트는 리렌더링이 이루어진 것이었다!
- 같은 이유로 MyComponent2는 MyComponent3이 리렌더링 되더라도, 이전의 MyComponent3을 기억하고 사용하기 때문에 리렌더링 되지 않는다.
참고자료
'TIL > React' 카테고리의 다른 글
[240327] 모던 리액트 딥 다이브 스터디 3주차 - (1) useContext (0) | 2024.03.27 |
---|---|
[240320] 리액트의 렌더링, 렌더링 최적화, 메모이제이션 (0) | 2024.03.20 |
[240207] 리액트의 가상 돔(Virtual DOM) (1) | 2024.02.07 |
[240205] 리액트 라이프사이클, useEffect (0) | 2024.02.05 |