2024. 6. 10. 16:57ㆍ리액트 (React)/리액트 레시피 (React Recipt)
5장부터는 UI가 개선되었습니다.
모든 예제 소스는 github repository 에서 확인할 수 있습니다.
State
사용자 입력을 받거나, 이미지를 교체하는 등 어떤 상태를 저장하고 이를 통해 표현할 일이 생깁니다.
이때 state를 사용하면 됩니다.
예를 들어 아래처럼 메시지를 누르면 숨길 수 있고, 아니면 원상 복귀되도록 만든다고 하면
다음과 같이 useState를 통해 state 변수를 만들어서 조건부 렌더링을 만들면 됩니다.
import { useState } from "react";
import "./Message.scss";
export default function Message(...) {
const [hidden, setHidden] = useState<boolean>(false);
return (
<div
className={`message-box ${isOutgoing ? "out" : "in"}`}
onClick={() => setHidden(!hidden)}
>
<span className="message-line">
{hidden ? <i className="fa-solid fa-lock" /> : message}
</span>
{checked && <i className="fa-solid fa-check" />}
</div>
);
}
예제 코드를 설명해보면, 먼저 state는 useState 훅(hook)을 통해 만들 수 있습니다.
이때 두 개 변수를 만들 수 있는데, 전자는 상태 변수이고 후자는 set 함수입니다.
const [hidden, setHidden] = useState<boolean>(false);
set 함수는 위 예시에서 div 태그를 누르면 본래 hidden 값의 반대가 되도록 사용했습니다.
<div ... onClick={() => setHidden(!hidden)}>
Rendering
state가 가지는 가장 중요한 역할은 바로 리렌더링(re-rendering)입니다.
여기서 렌더링이란 우리가 열심히 만든 컴포넌트들을 어떻게 화면에 보여줄 지 구성하는 것입니다.
state의 값이 변경되면, 다시 렌더링을 시작합니다.
즉, 최초에는 루트 컴포넌트(root component)부터 시작해서 연결되어있는 모든 컴포넌트를 렌더링하지만,
이후부터는 해당 state가 변경된 컴포넌트를 다시 렌더링 합니다.
더 자세히 설명해보면, 먼저 리액트는 컴포넌트들을 트리(tree) 구조로 생각하고 있습니다.
최초에는 App부터 Message까지 모든 컴포넌트들을 렌더링합니다.
이후 만약에 두 번째 Message의 hidden state를 변경해주면 해당 컴포넌트만 다시 렌더링되는 것입니다.
그렇다면 Screen의 하위 컴포넌트들은 건드리지 않고, 내부 태그값만 바꾸는 건 어떨까요?
특정 ms 초마다 콜백 함수를 호출하는 기능을 가진 setInterval 함수로 상태값을 1초마다 바꿔보도록 합니다.
import { ReactNode, useState } from "react";
import "./Screen.scss";
export default function Screen({ children }: { children: ReactNode }) {
const [currentText, setCurrentText] = useState<string>(new Date().toTimeString());
setInterval(() => setCurrentText(new Date().toTimeString()), 1000);
return (
<div className="screen">
{children}
<div>{currentText}</div>
</div>
);
}
이때는 오직 Screen만 다시 렌더링하게 됩니다.
만일 여기서 input을 놓으면 어떻게 될까요?
Screen이 다시 렌더링 되었으니, input에 작성했던 텍스트가 1초마다 사라질까요?
import { ReactNode, useState } from "react";
import "./Screen.scss";
export default function Screen({ children }: { children: ReactNode }) {
...
return (
<div className="screen">
{children}
<div>{currentText}</div>
<input />
</div>
);
}
아닙니다. 오직 시간 div만 변경되는 걸 확인할 수 있습니다.
이는 컴포넌트를 리렌더링해서 나온 결과를 이전 DOM 노드들과 비교하여 다른 부분만 수정하기 때문입니다.
즉 요약하면 최초 렌더링 이후 특정 컴포넌트의 state가 변경되면,
- 해당 컴포넌트를 찾는다
- 해당 컴포넌트만 다시 렌더링한다.
- 렌더링 결과를 이전 DOM 노드들과 비교해서 다른 부분만 수정한다.
를 수행합니다.
References
'리액트 (React) > 리액트 레시피 (React Recipt)' 카테고리의 다른 글
7. State 보존하기 (0) | 2024.06.11 |
---|---|
6. 인터렉티브한 Input 만들기 (0) | 2024.06.10 |
4. CSS 입히기 (0) | 2024.06.10 |
3. 조건부 렌더링 사용하기 (0) | 2024.06.09 |
2. Props 전달하기 (0) | 2024.06.09 |