본문 바로가기

클라이언트/React
[리액트(React)] Hook

// Hook

- function 컴포넌트에서 class컴포넌트와 동일한 기능을 사용할 수 있게 해준다.

- 이름 앞에 use를 붙여 hook임을 나타낸다.

- 최상위 컴포넌트에서만 호출해야 한다.

- 렌더링될 때마다 늘 같은 순서로 호출되어야 한다.(조건문x)

- 중첩된 함수나 if문 등에서 사용할 수 없다.


// useState

- state를 사용하기 위한 hook

const [ 변수명, set변수명 ] = usetState(초기값);

import React, { useState } from 'react';

function Counter(props) {
  const [count, setCount] = useState(1);

  return (
    <div>
      <p>총 {count}번 클릭했습니다.</p>
      <button onClick={() => setCount(count + 1)}>클릭</button>
    </div>
  );
}

export default Counter;

// useEffect()

- side effect를 수행하기 위한 hook

- side effect를 잘못 수행할 경우 무한루프에 빠지기 쉽기 때문에 useEffect hook을 사용한다.

- 생명주기 함수와 동일한 기능을 수행할 수 있다.

useEffect(effect함수, 의존성 배열);


- 의존성 배열이 빈 배열일 경우, 앱 컴포넌트 함수가 처음으로 실행된 이후 effect 함수는 단 한 번만 실행된다.

useEffect(effect함수, []);


- 의존성 배열을 생략할 경우, 컴포넌트가 업데이트될 때마다 실행된다.

useEffect(effect함수);

 

// effect 의존성
- useEffect 함수 안에서 사용되어 컴포넌트 함수를 다시 실행하도록 하는 값

import React, { useEffect, useState } from 'react';

const styles = {
  content: {
    padding: 10,
  },
};

function UseEffect(props) {
  const [count, setCount] = useState(0);

  useEffect(() => {
    document.title = `${count}`;
  });

  return (
    <div style={styles.content}>
      <p>{count}번 클릭</p>
      <button onClick={() => setCount(count + 1)}>클릭</button>
    </div>
  );
}

export default UseEffect;

// useMemo

- 저장된 값(Memoized value)를 반환하는 hook

- 컴포넌트가 렌더링 되는 동안 실행된다.

const 변수명 = useMemo(
  () => {
    return computeExpensiveValue(의존성 변수1, 의존성 변수2)
  },
  [의존성 변수1, 의존성 변수2]
)


- 의존성 배열이 빈 배열일 경우, 컴포넌트 마운트 시에만 실행된다.

const 변수명 = useMemo(
  () => {
    return computeExpensiveValue(의존성 변수1, 의존성 변수2)
  },
  []
)


- 의존성 배열을 생략할 경우, 렌더링할 때마다 실행된다.

const 변수명 = useMemo(
  () => {
    return computeExpensiveValue(의존성 변수1, 의존성 변수2)
  }
)

// useCallback

- 함수를 반환하는 hook

const 변수명 = useCallback(
  () => {
    함수명(의존성 변수1, 의존성 변수2)
  },
  [의존성 변수1, 의존성 변수2]
)


- 안쪽에 있는 함수를 메모리로써 내부에 저장하여 재생성 되지 않게 해준다.


function App() {
  const handleRemovePlace = useCallback(function handleRemovePlace() {
    setPickedPlaces((prevPickedPlaces) =>
      prevPickedPlaces.filter((place) => place.id !== selectedPlace.current),
    );
    setModalIsOpen(false);

    const storedIDs = JSON.parse(localStorage.getItem('selectedPlaces')) || [];
    localStorage.setItem(
      'selectedPlaces',
      JSON.stringify(storedIDs.filter((id) => id !== selectedPlace.current)),
    );
  }, []);

  return (
    <>
      <Modal open={modalIsOpen} onClose={handleStopRemovePlace}>
        {modalIsOpen && (
          <DeleteConfirmation
            onCancel={handleStopRemovePlace}
            onConfirm={handleRemovePlace}
          />
        )}
      </Modal>
    </>
  );
}

export default App;

 

function Modal({ open, onClose, children }) {
  const dialog = useRef();

  useEffect(() => {
    if (open) {
      dialog.current.showModal();
    } else {
      dialog.current.close();
    }
  }, [open]);

  return createPortal(
    <dialog className="modal" ref={dialog} onClose={onClose}>
      {open ? children : null}
    </dialog>,
    document.getElementById('modal'),
  );
}

export default Modal;

// useRef

- reference를 사용하기 위한 hook
   ~ reference: 특정 컴포넌트에 접근할 수 있는 객체

- 내부의 데이터가 변경되어도 다시 렌더링하지 않는다.

const 변수명 = userRef(초깃값);

// useSearchParams

- Query parameter를 받아올 수 있다.

const [searchParams, setSearchParams] = useSearchParams();
const 변수명 = searchParams.get('queryKey');