부모 컴포넌트에서 n번째 자식 컴포넌트로 데이터를 전달할 때, props를 사용하게 되면 props->props->props->props ... 처럼 불필요한 데이터 전달과 컴포넌트들을 스쳐가게 된다. 부모 컴포넌트에서 n번째 자식 컴포넌트로 데이터를 전달할 때 다른 컴포넌트들을 거치지 않고 한 번에 전달할 때 useContext 를 사용한다.
import React, { createContext } from "react"; const UserInfo = createContext(null); const App = () => { return ( <UserInfo.Provider value={{ name: "ayden", id: "1" }}> <User /> </UserInfo.Provider> ); }; const User = ()=>{ return ( <UserInfo.Consumer> {(value)=> ( <span>{value.name}</span> <span>{value.id}</span> )} </UserInfo.Consumer> ) }
위 코드는 Context API를 사용한 예시이다.
.Provider
를 사용해 값을 초기화한 동시에 사용할 수 있고
.Consumer
를 사용해createContext
에서 초기화 한 값과.Provider
로 재할당한 값을 사용할 수 있다.
✍ useContext Hook 사용
import React, { createContext } from "react"; const UserInfo = createContext({ name: "ayden", id: "1" }); const User = () => { const { name, id } = useContext(UserInfo); return ( <div> <h2>{name}</h2> <strong>{id}</strong> </div> ); };
API를 사용한 것보다 간단하고 쉽지만 함수형 컴포넌트에서만 사용 가능하다.
🕵️♀️ React의 생명 주기란?
LifeCycle은 클래스형 컴포넌트의 생명 주기고,
Hook Flow는 함수형 컴포넌트의 생명 주기라고 생각하면 된다.
다만, LifeCycle != Hook Flow 로 별개이다.
React는 컴포넌트가 실행, 업데이트되거나 제거될 때 특정 메서드를 호출한다. 따라서, 어떠한 구현 기능을 특정 시점에서 실행하기 위해 생명 주기를 알고 있어야 한다.
✍ LifeCycle
Mount : 처음 컴포넌트가 나타났을 때, 초기화된 state 값과 props를 가지고 컴포넌트를 생성.
- constructor : 컴포넌트가 render 되기 전에 호출, context, defaultProps와 state를 저장.
- render : React DOM을 렌더링하기 위해 호출.
- componentDidMount : Mount가 완료된 후(컴포넌트를 DOM에 부착한 후) 호출
Update : 마운트가 완전히 완료된 후 상태값이나 prop의 변화가 생겼을 때, 리액트는 이를 감지하고 컴포넌트에 업데이트.
- render : React DOM을 렌더링하기 위해 호출.
- componentDidUpdate : 업데이트가 완료된 후 호출.
Unmount : 컴포넌트가 사라질 때, 컴포넌트를 완전히 DOM에서 제거하는 시점.
- componentWillUnmount : 컴포넌트가 사라지기 바로 직전에 호출.
✍ Hook Flow
useState 와 useEffect 사용 통해 클래스의 componentDidMount, componentDidUpdate, componentWillUnmount와 같은 목적으로 생명 주기를 관리할 수 있다.
✍ Hook(함수형) 생명 주기
- Run lazy initializers : 컴포넌트가 만들어 질 때 props, state 등의 값을 초기화한다. 최초 마운트가 될 때 단 1번 실행.
- render : React DOM을 렌더링하기 위해 호출.
- React updates DOM : 렌더링된 DOM과 기존 DOM을 기반으로 업데이트 진행.
- Cleanup LayoutEffects : 업데이트/언마운트 과정에서 실행.업데이트 과정에서는 Run LayoutEffects 이전, 언마운트 과정에서는 컴포넌트가 제거되기 전에 동작.
- Run LayoutEffects : 마운트/업데이트 과정에서 컴포넌트가 브라우저에 그려지기 전에 동작.
- Browser paints screen : 만들어진 React DOM들을 브라우저에 그려짐.
- Cleanup Effects : 업데이트/언마운트 과정에서 실행. Run Effects 이전, 언마운트 과정에서는 컴포넌트가 제거되기 전에 동작.
- Run Effects : 마운트/업데이트 과정에서 컴포넌트가 브라우저에 그려진 후에 동작.
// 모든 컴포넌트가 렌더링 될 때 마다 호출.
useEffect(() => {
// 동작 구현
})
------------------------------------------------
// 클래스의 componentDidMount
// 렌더링이 완료된 후 호출, 마운트 이후 1회만 실행
useEffect(() => {
// 동작 구현
}, [])
------------------------------------------------
// 클래스의 componentDidUpdate
// 컴포넌트 업데이트 후 실행, state 변경될 때 마다 실행.
useEffect(() => {
// 동작 구현
}, [state명])
------------------------------------------------
// 클래스의 componentWillUnmount
// 컴포넌트가 DOM에서 제거 직전 실행.(clean-up)
useEffect(() => {
// 동작 구현
return () => {
//
}
}, [state명])
useLayoutEffect(() => {
console.log("마운트/업데이트 될때마다 브라우저에 그려주기 전에 실행");
return ()=>{
console.log("업데이트가 될때, 언마운트될때 실행")
}
});
-------------------------------------------------------
useEffect(() => {
console.log("마운트/업데이트 될때마다 브라우저에 그려진 후 실행!");
return ()=>{
console.log("업데이트가 될때, 언마운트될때 실행!")
}
});
❓ 그래서 둘의 차이는?
useLayoutEffect는 동기적으로 Render 과정과 Paint 과정 사이에서 동작한다.
useEffect는 비동기적으로 Paint 과정 이후에 동작한다.