리액트 앱에서 컴포넌트의 상태를 다루는 방법은 크게 2가지 입니다.
상태 (state)
속성 (props)
Object.freeze
로 불변성을 가진 읽기 전용으로 다룹니다.
속성
은 리액트 컴포넌트에 전달되는 데이터입니다.
보통 부모 컴포넌트가 전달합니다.
컴포넌트 자체의 defaultProps
정적 메서드를 통해 전달할 수도 있습니다. 👇
export default class Hello extends Component {
}
Hello.defaultProps = {
name:"초기값"
}
리액트 컴포넌트 내에서는 state를 직접 업데이트 해서는 안됩니다.
setState
가 state를 곧바로 갱신하는 것이 아니라 상태 전환을 pending 합니다. (비동기)
setState()
메서드를 호출한 후에 직접 state
에 접근하게 되면 갱신 되지 않은 기존의 값이 리턴될 가능성이 있어요.
이는 디버깅이 어려운 상태가 될 수 있기에 확실히 기존 데이터와는 다름을 알려주는 불변 데이터
로 다뤄야 합니다.
(아래에서 조금 더 이야기 해봅시다.)
얕은 비교
리액트는 상태 변화로 View를 리렌더링합니다.
그 과정에서 얕은 비교를 수행
합니다. (원시값은 바로 비교, 참조값은 참조하는 주소를 비교)
즉, 불변 객체로 다루면 주소값만으로도 변화를 감지할 수 있습니다.
React에서 props는 부모에서 자식으로 흐릅니다.
즉, React는 부모 노드를 렌더링하고 자식 노드에게 props을 전달하면 이제 부모 노드는 렌더링이 끝난 상태입니다.
그런데 만약 여기서 자식 노드가 props를 변경한다면 부모 노드는 다시 렌더링이 될 수 있을까요? → 이미 렌더링이 완료된 상태인데 불가능하겠죠.
이로 인해 이상한 동작이 발생할 수 있습니다.
(앱의 한 부분에 하나의 값이 있고 다른 부분에 다른 값이 있을 수 있으며 다음에 렌더링이 트리거 될 때 자체적으로 업데이트 될 수 있겠죠😢😢)
데이터 전파.. 오래 걸려..
하위 컴포넌트에서 Props를 직접 수정하면 양방향 바인딩
이 되겠네요.
Angular 1에는 양방향 바인딩으로 언제 어디서나 모든 데이터를 변경할 수 있다고 해요.
그러다보니 모든 데이터가 전파
를 마칠 때까지 DOM을 다시 렌더링하여 주위를 돌아 다니는 작업을 반복
합니다.
😢 결국 Angular 1이 너무 느려지게 되었어요.
Prop Drilling
을 해결할 수 있는 방법은? 1. Context API, Redux 같은 State Container
2. Store Management
또,children을 적극 활용하는 방법도 있습니다.
👇 예시를 보실까요?
import React from "react";
import "./styles.css";
export default function App() {
const content = "Who needs me?";
return (
<div className="App">
<FirstComponent>
<SecondComponent>
<ThirdComponent>
<ComponentNeedingProps content={content} />
</ThirdComponent>
</SecondComponent>
</FirstComponent>
</div>
);
}
function FirstComponent({ children }) {
return (
<div>
<h3>I am the first component</h3>;
{ children }
</div>
);
}
function SecondComponent({ children }) {
return (
<div>
<h3>I am the second component</h3>;
{children}
</div>
);
}
function ThirdComponent({ children }) {
return (
<div>
<h3>I am the third component</h3>
{children}
</div>
);
}
function ComponentNeedingProps({ content }) {
return <h3>{content}</h3>
}
props로 자식에게 전달 전달하는 것은 우아하지 않죠.
대신 이렇게 children을 적극 활용한다면 필요한 컴포넌트에서만 props로 content를 넘겨줄 수 있습니다.