1회차에 이어서 2회차에서도 React의 기본적인 내용을 바탕으로 강의가 진행되었습니다. 이번 강의에서는 제가 알지 못했던 내용들도 있어 그 부분을 중심적으로 글을 작성하고 전체적인 내용은 함축하여 기록한 내용입니다.
Component 내부에서 관리하는 데이터로 사용자의 입력이나 네트워크 요청 등으로 변경 가능하며, 이를 통해 실시간으로 UI 업데이트하는데 사용
부모 Component에서 자식 Component로 전달되는 읽기 전용 데이터 이를 통해 자식 Component를 구성하는데 사용
상태란 컴포넌트 내부에서 관리됩니다. 사용자의 입력이나 네트워크 요청과 같은 동적인 내용을 담을 수 있으며, 이를 통해 UI를 실시간으로 업데이트 할 수 있어 좋은 사용자 경험을 할 수 있게 도와줍니다.
속성은 부모 컴포넌트에서 자식 컴포넌트로 전달한 읽기 전용 데이터를 의미합니다. 이를 통해 자식 컴포넌트는 부모의 데이터를 받아 렌더링하는데 사용할 수 있으며, 전달 받은 데이터가 부모 컴포넌트에서 업데이트 될 경우 자식 컴포넌트는 재렌더링을 하게 됩니다.
애니메이션과 같은 UI 업데이트를 처리할 때 유용한 hook입니다. 상태의 업데이트를 느리게하여, 사용자 인터페이스의 주요 부분이 빠르게 응답할 수 있도록 하고, 이를 통해 사용자 경험을 향상시킵니다.
const [isPending, startTransition] = useTransition();
- isPending: 트랜지션이 진행 중인지 여부를 나타내는 boolean 값
- startTransition: 트랜지션을 시작하는 함수, 비동기적으로 상태 업데이트를 수행
import { useState, useTransition } from 'react';
const App = () => {
const [input, setInput] = useState('');
const [list, setList] = useState([]);
// startTransition는 비동기적으로 상태 업데이트를 수행
const [isPending, startTransition] = useTransition();
const handleChange = (e) => {
const value = e.target.value;
setInput(value);
// 안의 작업이 끝나면 isPending이 false로 변경
startTransition(() => {
const updatedList = Array(20000)
.fill(0)
.map((_, index) => `${value} - Item ${index}`);
setList(updatedList);
});
};
return (
<div>
<input type='text' value={input} onChange={handleChange} />
{isPending ? (
<p>Loading...</p>
) : (
<ul>
{list.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
)}
</div>
);
};
부모 컴포넌트가 자식 컴포넌트의 인스턴스 메서드를 명시적으로 호출할 수 있도록 하는데 사용됩니다.
useImperativeHandle(ref, createHandle, [deps])
- ref: 부모 컴포넌트로 전달된 ref 객체
- createHandle: 부모 컴포넌트가 자식 컴포넌트에 접근할 수 있는 메서드나 속성을 반환하는 함수
- deps: 의존성 배열 안의 값이 변경될 때마다 createHandle이 다시 호출
import { useRef, useImperativeHandle, forwardRef, useState } from 'react';
// 자식 컴포넌트
const ChildComponent = forwardRef((props, ref) => {
const [value, setValue] = useState(0);
// ref: 부모 컴포넌트와 연결점
useImperativeHandle(ref, () => ({
increment: () => setValue((prev) => prev + 1),
decrement: () => setValue((prev) => prev - 1),
}));
return (
<div>
<p>Value: {value}</p>
</div>
);
});
// 부모 컴포넌트
const ParentComponent = () => {
const childRef = useRef();
return (
<div>
<ChildComponent ref={childRef} />
<button onClick={() => childRef.current.increment()}>Increment</button>
<button onClick={() => childRef.current.decrement()}>Decrement</button>
</div>
);
};
useEffect와 유사하지만 DOM 업데이트가 완료된 직후에 동기적으로 실행됩니다. 이 훅은 레이아웃을 읽거나 수정할 때 사용됩니다. useLayoutEffect는 브라우저가 화면을 그리기 전에 실행되므로, 화면이 깜박이는 문제를 방지할 수 있습니다.
useLayoutEffect(() => {
// DOM 업데이트 직후 실행될 코드
return () => {
// 정리 함수 (컴포넌트가 언마운트되거나 effect가 재실행되기 전에 호출)
};
}, [deps]); // 의존성 배열
import { useState, useRef, useLayoutEffect } from 'react';
const LayoutEffectExample = () => {
const [rect, setRect] = useState({ width: 0, height: 0 });
const divRef = useRef(null);
useLayoutEffect(() => {
// div의 크기를 측정하고 상태로 저장
if (divRef.current) {
const rect = divRef.current.getBoundingClientRect();
setRect({ width: rect.width, height: rect.height });
}
}, []); // 빈 배열을 전달하여 컴포넌트가 처음 렌더링될 때만 실행
return (
<div>
<div ref={divRef} style={{ width: '200px', height: '100px', backgroundColor: 'lightblue' }}>
Measure me!
</div>
<p>Width: {rect.width}px</p>
<p>Height: {rect.height}px</p>
</div>
);
};
useEffect는 컴포넌트가 렌더링된 후 비동기적으로 실행됩니다. 즉, 브라우저가 화면을 업데이트하고 그린 후에 실행됩니다. 비동기적으로 실행되기 때문에 주로 주로 데이터 가져오기, 구독 설정, DOM 업데이트와 같은 작업에 사용됩니다.
useLayoutEffect는 컴포넌트가 렌더링된 후, 브라우저가 화면을 그리기 전에 동기적으로 실행됩니다. 즉, DOM이 업데이트된 직후 바로 실행됩니다. 주로 레이아웃을 측정하고 조정하는 작업에 사용되는데 이를 통해 화면이 그려질 때 필요한 레이아웃 변경을 바로 적용할 수 있습니다.
class 컴포넌트에서는 componentDidMount, componentDidUpdate, componentWillUnmount 메서드를 사용하여 각각의 라이프사이클 단계에서 특정 작업을 수행할 수 있습니다.
class ExampleComponent extends Component {
componentDidMount() {
console.log('Component did mount');
}
componentDidUpdate(prevProps, prevState) {
console.log('Component did update');
}
componentWillUnmount() {
console.log('Component will unmount');
}
render() {
return <div>Example Component</div>;
}
useEffect는 함수형 컴포넌트에서 사이드 이펙트를 처리하는 데 사용됩니다. 하나의 훅으로 컴포넌트가 마운트될 때, 업데이트될 때, 그리고 언마운트될 때 수행해야 할 작업을 처리할 수 있습니다.
import { useEffect } from 'react';
const ExampleComponent = () => {
useEffect(() => {
// 마운트될 때 실행되는 코드
console.log('Component did mount');
// 업데이트될 때 실행되는 코드
console.log('Component did update');
// 언마운트될 때 실행되는 코드
return () => {
console.log('Component will unmount');
};
}, []); // 빈 배열이면 마운트와 언마운트 시에만 실행
};
class 컴포넌트와 function 컴포넌트의 차이를 잘 인지하고, 생명주기 메서드와 useEffect의 장단점을 이해하여 면접에 대비!!