useEffect = Hook
어떤 컴포넌트가 화면에 보여졌을 때 내가 무언가를 실행하고 싶다면? 또는 어떤 컴포넌트가 화면에서 사라졌을 때 무언가를 실행하고 싶다면? useEffect를 사용합니다.
import React, { useEffect } from "react"; 로 import 해서 사용합니다.
* useEffect와 배치 업데이트의 관계
React는 여러 상태 업데이트가 발생할 때 배치 업데이트를 통해 최적화합니다. 상태가 여러 번 변경되더라도 React는 이 상태 업데이트들을 모아서 하나의 렌더링 사이클로 처리합니다. 그리고 그 후에 useEffect가 실행됩니다.
useEffect를 사용하면, React가 모든 상태 업데이트와 렌더링을 완료한 후에 해당 로직이 실행되므로, 최신 상태를 기반으로 조건을 평가할 수 있습니다.
// src/App.js
import React, { useEffect } from "react";
const App = () => {
useEffect(() => {
// 이 부분이 실행된다.
console.log("hello useEffect");
});
return <div>Home</div>;
}
export default App;
App 컴포넌트가 화면에 렌더링 된 이후 useEffect 안에 있는 console.log가 실행.
의존성 배열[] 의 값이 변할때만! useEffect(()=>{}; []) 를 실행할게
// useEffect의 두번째 인자가 의존성 배열이 들어가는 곳.
useEffect(()=>{
// 실행하고 싶은 함수
}, [의존성배열])
어떤 함수를 컴포넌트가 렌더링 된 후 단 한번만 실행하고 싶으면 의존성 배열을 [ ] 빈 상태로!
컴포넌트가 unmount 될 때 동작하는 cleanup 함수
컴포넌트가 나타났을 때 (렌더링됐을 때 = 함수 컴포넌트가 실행됐을 때) 동작하는 것은 useEffect의 effect 함수입니다. cleanup 함수는 컴포넌트가 사라졌을 때 무언가를 어떻게 실행하는지
useEffect 안에서 return 을 해주고 이 부분에 실행되길 원하는 함수를 넣으면 된다 즉! 리턴문 다음에 함수를 쓰면 됨
// src/App.js
import React, { useEffect } from "react";
const App = () => {
useEffect(()=>{
// 화면에 컴포넌트가 나타났을(mount) 때 실행하고자 하는 함수를 넣어주세요.
return ()=>{
// 화면에서 컴포넌트가 사라졌을(unmount) 때 실행하고자 하는 함수를 넣어주세요.
}
}, [])
return <div>hello react!</div>
};
export default App;


useRef = Hook
Re-rendering과 상관없이 값을 기억. 렌더링이 되도 기존 값을 유지한다! useState와 같이 저장공간으로서 쓰이지만 useState는 렌더링을 일으킨다. useRef는 DOM요소에 접근함
✦ 렌더링은 화면 새로고침 (수정 반영)
import "./App.css";
import { useRef } from "react";
function App() {
const ref = useRef("초기값");
console.log("ref 1", ref);
ref.current = "바꾼 값";
console.log("ref 1", ref);
return (
<div>
<p>useRef에 대한 이야기에요.</p>
</div>
);
}
export default App;

import { useEffect, useRef } from "react";
import "./App.css";
function App() {
const idRef = useRef("");
// 렌더링이 될 때
useEffect(() => {
idRef.current.focus();
}, []);
return (
<>
<div>
아이디 : <input type="text" ref={idRef} />
</div>
<div>
비밀번호 : <input type="password" />
</div>
</>
);
}
export default App;

prop drilling 현상
부모 → 자식 → 그 자식 → 그자식의 자식 반복!!
그래서 등장한 것이 바로 react context API.
useContext hook을 통해 쉽게 전역 데이터를 관리.
createContext : context를 생성합니다.useContext : context를 구독하고 해당 context의 현재 값을 읽습니다.Provider : context를 하위 컴포넌트에게 전달합니다.
// context > FamilyContext.js 생성
import { createContext } from "react";
// null에
export const FamilyContext = createContext(null);
// GrandFather.jsx
import React from "react";
import Father from "./Father";
import { FamilyContext } from "../context/FamilyContext";
function GrandFather() {
const houseName = "스파르타";
const pocketMoney = 10000;
return (
<FamilyContext.Provider value={{ houseName, pocketMoney }}>
<Father />
</FamilyContext.Provider>
);
}
export default GrandFather;
// Father.jsx 수정
import React from "react";
import Child from "./Child";
function Father({ houseName, pocketMoney }) {
return <Child houseName={houseName} pocketMoney={pocketMoney} />;
}
export default Father;
Father.jsx 수정(props를 제거
function Father({ houseName, pocketMoney }) {
return <Child houseName={houseName} pocketMoney={pocketMoney} />;
}
// Child.jsx 수정
import React, { useContext } from "react";
import { FamilyContext } from "../context/FamilyContext";
function Child({ houseName, pocketMoney }) {
const stressedWord = {
color: "red",
fontWeight: "900",
};
const data = useContext(FamilyContext);
console.log("data", data);
return (
<div>
나는 이 집안의 막내에요.
<br />
할아버지가 우리 집 이름은 <span style={stressedWord}>{data.houseName}</span>
라고 하셨어요.
<br />
게다가 용돈도 <span style={stressedWord}>{data.pocketMoney}</span>원만큼이나
주셨답니다.
</div>
);
}
export default Child;
import { FamilyContext } from "../context/FamilyContext";
~~
~~const data = useContext(FamilyContext);
console.log("data", data);

useContext로 prop drilling 현상 해결!
단계별로 보는 useContext
import React, { createContext } from 'react';
// Context 생성
const MyContext = createContext();
이제 MyContext라는 Context를 만들었습니다.
이 Context는 데이터를 공급하고 소비하기 위해 사용됩니다.
import React from 'react';
import MyContext from './MyContext';
function App() {
const user = { name: 'John Doe', age: 30 };
return (
<MyContext.Provider value={user}>
<UserProfile />
</MyContext.Provider>
);
}
여기서 user라는 객체를 MyContext.Provider의 value로 전달했습니다.
이제 UserProfile 컴포넌트와 그 하위 컴포넌트는 이 user 데이터를 사용할 수 있습니다.
자식 컴포넌트(UserProfile)는 useContext 훅을 사용해 MyContext로부터 부모 컴포넌트가 제공한 user 데이터를 가져옵니다.
useContext(MyContext): MyContext에서 제공된 user 객체를 가져옵니다. 이 객체는 부모 컴포넌트(App)에서 Provider를 통해 전달된 것입니다.
import React, { useContext } from 'react';
import MyContext from './MyContext';
function UserProfile() {
const user = useContext(MyContext);
return (
<div>
<h1>Name: {user.name}</h1>
<h2>Age: {user.age}</h2>
</div>
);
}
useContext(MyContext): MyContext에서 제공된 user 객체를 가져옵니다.
이제 user 데이터를 UserProfile 컴포넌트에서 사용할 수 있습니다.