📌 TypeScript로 HTML 요소 조작하기
1 | // index.ts |
1 | // index.ts |
함수 컴포넌트는 렌더링 될 때 마다 몸체가 다시 실행되므로 컨텍스트를 기억하기 위해 Hook을 사용한다. 그리고 상위 컴포넌트는 기억된 상태 또는 업데이트 함수를 하위 컴포넌트에게 전달한다.
이 때 상위 컴포넌트가 다시 실행되면
useCallback()
은 하위 컴포넌트에 전달되는 함수를 기억해두고 이를 이용하여 컴포넌트 업데이트 시 리렌더링이 발생할 때, 기억된 함수를 사용해 불필요한 리렌더링을 줄여 성능을 높이기 위해 사용한다.
1 | export function Counter({ count: initialCount, step }) { |
1 | useCallback(fn, deps) === useMemo(() => fn, deps); |
useMemo()는 JavaScript 데이터 타입을 기억해야 할 때 사용합니다. 만약 기억해야할 타입이 함수라면 useCallback을 사용한다.
1 | export function Counter({ count: initialCount, step }) { |
[count, onDecrement, onIncrement, restProps]
이 변경되면 useMemo가 반환하는 값을 기억하고 실행한다.setCount()
를 기억하고 있어 동일참조를 하므로 count 값을 기억하고 있다.값을 기억하는 목적으로 좋지만… 굳이 이것을 사용하려고 복잡하게 또 많은 시간을 할애할 필요가 있을까 ?
리액트에서 ref는 주로 DOM 노드 참조 목적으로 사용된다. 컴포넌트 렌더링에 영향을 주지 않는 값 참조 목적으로 사용된다.
useRef()
는 함수 컴포넌트 내부에서 특정 값을 지속적으로 참조할 때 사용한다. useState()
와 달리 useRef()
는 현재 값이 변경되어도 컴포넌트가 다시 렌더링되지 않아 애플리케이션 성능을 최적화 할 수 있다.
1 | // useRef() 훅을 사용해 카운트 참조 생성 |
클래스는 자신의 인스턴스 멤버를 사용해 렌더링 상관없이 특정 값을 기억할 수 있는데 반해, 함수는 다시 렌더링 되면 매번 함수 몸체가 초기화 되므로 특정 값을 기억할 때 useRef()를 사용하면 유용하다.
리액트 render() 단계에서는 DOM이 그려지기 전 단계이므로
하지만 useRef()를 사용하여 컴포넌트가 mount된 시점 이후 DOM 요소에 접근하여 조작할 수 있도록 도와준다.
1 | function TextInputWithFocusButton() { |
함수 컴포넌트 내부에서 특정 값을 기억하면서 값을 변경해도 컴포넌트 렌더링에 영향을 주지 않아야한다.
1 | import { useEffect, useRef, useState } from "react"; |
useState()
의 setStateValue()
메서드를 사용하여 값을 변경한 경우 재렌더링이 발생하지만, useRef()
의 current 값을 갱신하면 재렌더링이 발생하지 않는다.타입 지정시 string, number 같은 원시타입만 할당할 수 있는 것이 아니다.
개발자가 지정한 글자나 숫자 들을 타입으로 지정할 수 있다.
1 | let john: "Texas"; |
1 | type Animal = string | number; |
1 | type NumOut = (x: number, y: number) => number; |
1 | useEffect(effectCallback); |
함수 컴포넌트에서 발생 가능한 side-effect(부수효과)를 관리하기 위해 사용한다.
리액트가 할 수 없는 작업을 할 때, useEffect()
를 사용한다.
리액트 Hook의 실행흐름은 위 사진과 같다.
함수 컴포넌트에서 클래스 컴포넌트의 생명주기를 구현하기 위해 useEffect()
가 componentDidMount()
, componentDidUpdate()
, componentWillUnmount()
메서드가 발생되는 주기를 대체할 수 있어야한다.
useEffect()가 이들을 100% 대체할 순 없지만 문제없을 정도로 흉내내어 사용하고 있다.
componentDidMount()
대체 방법1 | useEffect(() => { |
componentDidUpdate()
대체 방법1 | useEffect( |
componentWillUnmount()
대체 방법이벤트 구독/취소처럼 컴포넌트가 제거될 때 실행되어야 하는 함수의 경우 다음과 같이 사용한다.
1 | function Tester() { |
cleanUp
함수는 메모리 누수 방지를 위해 UI에서 컴포넌트를 제거하기 직전에 수행된다.이는 componentWillUnmount()
처럼 동작하는 것 같지만, 리액트 팀은 클래스 컴포넌트 생명주기대로 로직을 구현했을 때, 대규모 프로젝트에서 버그를 많이 발견하였다.
그리하여 리액트 팀에서는 구독취소 후 다시 구독하는 과정을 통해 이를 구현하였다.
1 | useEffect(() => { |
1 | const [stateValue, stateUpdater] = useState(initState); |
함수 컴포넌트에서 상태를 관리할 때 사용하는 API이다.
stateUpdater
는 보통 setStateValue
이런식으로 set을 붙혀서 사용한다.initState
값은 초기 렌더링 시에만 사용되는 값으로, 이후 렌더링 시에는 무시된다. 만약 초깃값을 계산하는데 많은 시간이 필요한 경우 콜백함수를 통해 지연된 초기화 처리가 가능하다.
1 | const [stateValue, stateUpdater] = useState(() => { |
updateState
함수는 setState
함수처럼 객체 상태를 관리하기 합성된 객체를 반환해야 한다.
1 | const [state, updateState] = useState({ |
updateState
함수는 상태 병합이 아닌 대체를 하므로 변경되지 않는 객체 값을 유지하기 위해서 위와 같이 해야한다.리액트 Hook은 클래스로 컴포넌트를 만들 때 발생하는 문제점을 해결하기 위해 등장하였다.
모든 JavaScript는 TypeScript이지만,
1 | interface State { |
위 예시를 설명하면, 앞서 말한 모든 타입스크립트가 자바스크립트다
JavaScript는 동적 타입만을 제공하여 예측하기 어려운 타입변환으로 디버깅이 어려워지는 문제점이 있어 이를 해결하고자 TypeScript가 탄생하였다.
TypeScript는 정적 타입 시스템을 사용하여 코드가 실행되기 전에 코드에 대하여 예측해준다.
계속 읽기author.bio
author.job