Hooks

zmin·2022년 7월 15일
0

기존 책에서 참고한 hooks를 토대로 작성했던 블로그글을
docs를 읽으며 수정

클래스형 컴포넌트에 있던 state와 lifecycle method들을
함수형 컴포넌트에서도 사용할 수 있도록 만들어 줌
→ 그저 UI를 그릴 뿐이었던 함수형 컴포넌트의 활용성을 늘림

또한 내가 느꼈던 편리함은 한 컴포넌트에서 하나의 state이용하여 사용할 상태들을 모두 객체 형태로 전부 집어 넣었던 것을
이 hooks를 이용하면 각 상태를 개별로 관리 가능하다는 것이다.

Hooks allow you to reuse stateful logic without changing your component hierarchy
뿐만 아니라 기존의 상태 관리를 개선한 형태
무조건 컴포넌트로 사용될 곳과 클래스에서만 hooks를 사용할 수 있는 것이 아니라 함수 내부에서 사용하여 상태관리 함수를 만들어 여러곳에 이용할 수 있다.말 그대로 재사용성이 높아지는 것


함수형 컴포넌트에서만 사용가능하나 고차 컴포넌트를 이용하면 클래스 컴포넌트에서도 간접적으로 사용가능
→ 만약 기존의 클래스형 리액트 앱에 함수형 컴포넌트를 덧붙이는 것이 아니라면 그냥 함수형 컴포넌트로 사용하는 것이 좋을 것 같음

상태 관리 Hooks

함수가 종료됐을 때 변수는 사라지지만 state는 유지

useState

함수형 컴포넌트에서도 state를 사용할 수 있도록 함
한 번에 여러가지 상태를 관리할 수 있음
아래와 같이 사용

import {useState} from 'react';

const [상태, 상태변경함수] = useState(초기값);
// 상태변경함수의 경우 보통 'set상태'로 사용하는 경우가 대부분
// 비구조화 할당을 이용하는 것이 어떤 것인지 명시하기 좋기 때문에 주로 사용


//ex
const [name, setName] = useState("망구");
const [age, setAge] = useState(0);

setName("구망");
setAge(age + 5);
// name === '구망', age === '5'

초기값을 설정할 때 고비용의 연산이 필요하다면 아래와 같이 initialState인자를 이용하여 초기 렌더링 시에만 연산하도록 함수를 제공할 수 있음

const [state, setState] = useState(() => {
  const initialState = someExpensiveComputation(props);
  return initialState;
});

그리고 유의해야 할 점이 useState안에서 배열이나 객체를 수정해야한다면 단순히 그 값만 수정해선 안됨 -> 이는 클래스 state와 동일

해당 값만 수정된 배열/객체를 통째로 setLecture에 넣어주어야함
(스프레드 연산자 사용 가능)

//ex
const [lecture, setLecture] = useState({
  name : 'computer science',
  student : 30,
  classroom : 'B101'
});

setLecture({
  ...lecture,
  student : 29
});

useEffect

기본적으로 해당 컴포넌트의 렌더링 후 실행
클래스형 컴포넌트의 라이프사이클메소드 일부의 역할을 함

컴포넌트를 생명주기에 맞추어 생각하기 보단 상태 값들에 집중하여 작업을 처리
작업 시점의 기준은 기본적으로 렌더링 후

기본적으로 아래와 같은 형태를 띄고 있으며 이 경우 모든 렌더링(첫 마운트+업데이트) 이후 실행되게 됨

import {useEffect} from 'react';

useEffect(() => {
  //렌더링 후 실행할 코드
});

만약 모든 렌더링이 아니라 특정 값이 변화했을 때만 useEffect()를 실행하고 싶다면 함수의 두 번째 파라미터로 [원하는값] 을 전달해주면 됨
빈 배열 [] 을 전달할 경우 첫 마운트에만 실행됨

useEffect(() => {
  
  //...
  
}, [원하는값]);

아래와 같이 useEffect()에 반환할 함수를 지정해주면 해당 함수가 실행되는 렌더링 전에 실행할 작업을 지정해줄 수 있음.
빈 배열 [] 을 전달할 경우 언마운트에만 실행됨

useEffect(() => {
  
  //...
  
  return(() => {
    //렌더링 전, 언마운트 시 실행할 코드
  });
},[원하는값]);

second parameter로 넘겨준 인자에 대해 prevState를 굳이 추가해주지 않아도 알아서 비교한 뒤 변경사항이 있을 때만 effect 실행 (굉.편. 굉장히 편리라는 뜻)

클래스형 컴포넌트의 경우 이를 prevState를 명시하여 비교해주는 작업이 필요함

componentDidUpdate(prevProps, prevState){
	if (prevState.value !== this.state.value) {
    	// 값이 변경됐을 때 실행하고 싶은 것
    }
}

그 렇 다 면 second parameter 배열로 state만 전달가능한가?

props도 가능하지만 일반적인 variable은 전달 불가능

  • props는 상위 컴포넌트에서 전달되는 값이라 리액트가 이전 값을 기억하고 변경되었는지 확인이 가능하지만
  • 일반적인 variable은 해당 컴포넌트가 다시 렌더링 되면서 사라지고 다시 나타나는 것이기 때문에 이전 값을 까먹버림
    그니까 useEffect에서는 처음보는 애를 들이밀면서 이거 바뀌었냐고 묻는셈. 꽤나 황당할 법하다.

useContext

전역값을 관리할 수 있도록 도와주는 hook

다른 Hooks

useReducer

useState와 같은 기능적으로는 같으나 local 단위의 상태값을 관리할 수 있게 해줌
좀 넓은 범위의 배열 메소드의 reduce를 생각할 수 있을 것 같음

function customReducer(state, action){
  switch(action.type) {
    case 'TYPE1' :
      return {
        ...state,
        value : state.value + 1
      };
    case 'TYPE2' :
      return {
        ...state,
        value : state.value + 2
      };
    default:
      return state;
  }
}


const [state, dispatch] = useReducer(customReducer, { 
  value : 0,
  date : '2022-01-20'
});

dispatch({type : 'TYPE1'});

컴포넌트 바깥으로 업데이트 로직(customReducer 함수)을 빼낼 수 있음
또한 action 값으로 다양한 객체를 받을 수 있음 e.target을 이용하여 이벤트가 발생한 객체를 전달하는 것도 가능

예시 코드를 보면 해당 값을 다양한 액션으로 관리할 때 사용할 수있어 편리

useMemo & useCallback

재사용성을 높여줌
특정 값이 변화했을 때만 함수를 호출하거나 함수를 새로 생성할 수 있음
두 함수의 첫 번째 파라미터에는 호출하고 싶은 함수/생성하고 싶은 함수를 전달하고
두 번째 파라미터에 어떤 값이 변했을 때 이 hooks를 실행할 건지에 대해 배열 형태로 전달
비어있는 배열을 전달할 경우 첫 번째 렌더링(마운트)시에만 실행됨

// useMemo
const [state, setState] = useState([]);
const result = useMemo(() => 어떤함수, [state]);
// 이 경우 어떤 함수의 반환 값이 result에 대입

// useCallback
const [state, setState] = useState([]);
const someFunction = useCallback(() => 어떤함수, [state]);
// 이 경우 someFunction이 어떤함수의 내용을 가지고 새로 선언됨

useMemo로 함수를 반환하고자 하는 것을 더 쉽게 도와주는 것이 useCallback
기본 원리나 의도는 비슷

useRef

함수형 컴포넌트에서 ref를 쉽게 사용할 수 있게하고(이때 사용법은 createRef와 동일)
컴포넌트의 전생명주기동안 유지되는 값을 지정할 수도 있다.
(는 추가 기능이며 매우 유용함)

const value = useRef(초깃값);

// 아래와 같이 배열로 ref를 여러개 사용할 수 있다
const ref = useRef([]);

<... ref={element => ref.current[0] = element} ... />
<... ref={element => ref.current[1] = element} ... />

custom Hooks

custom hooks라고 하면 useState를 떠올리면서 상태로 사용할 값과 상태를 변경하는 함수를 반환하는 그런 것을 떠올릴 수도 있을 것 같은데(나처럼)
그건 hooks의 일부일 뿐이고...

큰 범위의 hooks는 상태를 관리하는 것을 도와주는 것이다

그래서 공식 문서의 useFriendStatus를 살펴보면 알 수 있듯이 이 custom Hook은 friend 구독 상태를 관리하는 하나의 'hook'인 것

반환하는 값에 집중할 것이 아님. 논점을 벗어나지 말 것...


참고자료

https://ko.reactjs.org/docs/hooks-reference.html
리액트를 다루는 기술, 김민준

profile
308 Permanent Redirect

0개의 댓글