Tan Kim

React

Meta가 만든 UI 라이브러리. 컴포넌트 단위로 UI를 구성하고, 상태 변화에 따라 자동으로 리렌더링한다.

컴포넌트

// 함수형 컴포넌트 (현재 표준)
function Hello({ name }: { name: string }) {
  return <h1>안녕, {name}</h1>
}

Hooks

useState

const [count, setCount] = useState(0)
 
setCount(count + 1)          // 직접 값 지정
setCount((prev) => prev + 1) // 이전 상태 기반 (권장)

useEffect

// 마운트 시 1회
useEffect(() => {
  fetchData()
}, [])
 
// 의존성 변경 시
useEffect(() => {
  fetchUser(userId)
}, [userId])
 
// 클린업 (언마운트 or 재실행 전)
useEffect(() => {
  const timer = setInterval(() => {}, 1000)
  return () => clearInterval(timer)
}, [])

useRef

// DOM 접근
const inputRef = useRef<HTMLInputElement>(null)
inputRef.current?.focus()
 
// 리렌더링 없이 값 유지
const countRef = useRef(0)
countRef.current += 1

useMemo / useCallback

// 값 메모이제이션 (연산 비용이 클 때)
const sorted = useMemo(() => items.sort(), [items])
 
// 함수 메모이제이션 (자식 컴포넌트에 props로 넘길 때)
const handleClick = useCallback(() => {
  doSomething(id)
}, [id])

useContext

const ThemeContext = createContext<'light' | 'dark'>('light')
 
// Provider
<ThemeContext.Provider value="dark">
  <App />
</ThemeContext.Provider>
 
// 사용
const theme = useContext(ThemeContext)

useReducer

type Action = { type: 'increment' } | { type: 'reset' }
 
function reducer(state: number, action: Action) {
  switch (action.type) {
    case 'increment': return state + 1
    case 'reset':     return 0
  }
}
 
const [count, dispatch] = useReducer(reducer, 0)
dispatch({ type: 'increment' })

커스텀 Hook

반복되는 로직을 추출해 재사용.

function useFetch<T>(url: string) {
  const [data, setData] = useState<T | null>(null)
  const [loading, setLoading] = useState(true)
 
  useEffect(() => {
    fetch(url)
      .then((res) => res.json())
      .then((data) => { setData(data); setLoading(false) })
  }, [url])
 
  return { data, loading }
}
 
// 사용
const { data, loading } = useFetch<User[]>('/api/users')

렌더링 최적화

// React.memo — props가 바뀌지 않으면 리렌더링 스킵
const Child = React.memo(({ value }: { value: number }) => {
  return <div>{value}</div>
})
도구 용도
React.memo 컴포넌트 리렌더링 방지
useMemo 값 재계산 방지
useCallback 함수 재생성 방지

이벤트 처리

// 타입 명시
function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
  setValue(e.target.value)
}
 
function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
  e.preventDefault()
}

조건부 렌더링 & 리스트

// 조건부
{isLoggedIn && <Dashboard />}
{isLoggedIn ? <Dashboard /> : <Login />}
 
// 리스트 (key 필수)
{items.map((item) => (
  <li key={item.id}>{item.name}</li>
))}

메모