[React] Hooks

박영준·2020년 12월 27일
0

Hook

Hook은 함수 컴포넌트에서 react state와 lifecylcle을 연동 할 수 있게 해주는 함수이다.
hook은 class 안에서는 동작하지 않는다. 대신 class 없이 react를 사용할 수 있게 해준다.

Hook 사용규칙

  1. 최상위에서만 Hook을 호출해야 한다. 그리고 반복문, 조건문, 중첩된 함수 내에서는 Hook을 실행해서는 안된다.

  2. react 함수 컴포넌트 내에선만 hook을 호출해야 한다. 일반 javascript 함수에서는 hook을 호출해서는 안된다.

useState❗️

const [state, setState] = useState(initailState);

상태 유지 값과 그 값을 갱신하는 함수를 반환한다. 최초로 렌더링을 하는 동안, 반환된 state(state)는 첫번째 전달된 인자(intialState)의 값과 같다.

setState함수는 state를 갱신할 때 사용한다. 새 state 값을 받아 컴포넌트 리렌더링을 큐에 등록한다.

example code

// 클래스형 컴포넌트
class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  render() {
    return (
      <div>
        <p>You clicked {this.state.count} times</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Click me
        </button>
      </div>
    );
  }
}
import React, { useState } from 'react';

// 함수 컴포넌트
function Example() {
  // 새로운 state 변수를 선언하고, count라 부르겠습니다.
  const [count, setCount] = useState(0);
	const [isModalActive, setIsModalActive] = useState(false);
	
	// 안 좋은 예시
	const [state, setState] = useState({
		color: "red",
		isActive: true,
		name: "jt".
		password: "sdaf"
	})

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
			<button onClick={() => setIsModalActive(!isModalActive)}>modal btn</button>
    </div>
  );
}
  • 기존 setState와 마찬가지로 비동기 update
  • useState 실행 시 state, setState 한쌍이 부여됨
  • 기억해 둘 개념
    - 가비지 컬렉팅 : 더 이상 참조하는 곳이 없는 메모리에 대해서 실행
    • 클로저 : 자신이 생성될 시점의 환경을 기억하는 함수

함수는 상태를 저장하지 않는다고 했는데 어떻게 useState는 어떻게 상태값을 저장할까?

함수는 상태를 저장하지 않는다

함수는 실행이 완료되면 함수 내에서 사용했던 모든 메모리들을 정리한다. 이를 가비지 컬렉팅이라고 한다. 2018년 이전까지 React에서 상태관리 및 라이프사이클 API를 사용하기 위해 클래스형 컴포넌트를 사용했던 이유다.

하지만 함수가 언제나 가비지 컬렉터에 의해 사라지기만 하는 건 아니다. 실행이 끝나고도 메모리에 스스로를 남겨둘 수 있는 방법이 있다. 바로 클로저다.

하지만 클로저가 출동한다면 어떨까?

함수형 컴포넌트는 Hooks를 사용하면서 상태 관리가 가능해졌다. Hooks에서 state를 저장하려면 useState()를 사용한다. useState 역시 함수이며 클로저를 이용해 변수를 저장한다. 간단한 코드로 확인해보자.

const useState = (init = undefined) => {
  let value = init

  const getter = () => value // 클로저
  const setter = next => (value = next) // 클로저

  return [getter, setter]
}

const [state, setState] = useState('클로저')

위 코드는 간략하게나마 useState의 내부 구조를 보여주고 있다.

초기값을 받아 내부의 지역변수 value에 할당한다. 내부 함수 getter()는 지역변수 init을 바라보고 있다. 또 다른 내부 함수 setter()는 next라는 인자를 받아 value의 값을 수정한다. 이후 다시 getter()를 호출하게 되면 변경된 value의 값을 호출하게 된다.

두 함수는 배열 형태로 리턴되고 useState를 사용할 때는 배열 구조분해 할당 형태로 많이 사용하게 된다.

일반적인 함수라면 return과 함께 실행이 종료되고 나서 내부의 데이터들이 가비지 컬렉팅 되어야 하겠지만, 이 경우 내부 함수가 지역 변수를 참조하고 있으므로 사라지지 않는다.

또한 외부로 노출된 getter, setter 함수를 통해 내부 변수에 지속적으로 접근하며 호출/재할당을 할 수 있다. 이는 클래스형 컴포넌트에서 state가 해온 역할과 동일하다.

useEffect❗️

Effect Hook, 즉 useEffect는 함수 컴포넌트 내에서 이런 side effects를 수행할 수 있게 해준다. React class의 componentDidMount 나 componentDidUpdate, componentWillUnmount와 같은 목적으로 제공되지만, 하나의 API로 통합된 것이다.

useEffect(function);

useEffect(() => {}, [count]) // 의존성 배열 (배열 안에 담긴 값들을 추적, 그때 마다 업데이트)

componentDidMount와 같은 역할

useEffect(() => {
	console.log("componentDidMount")
	return () => console.log("componentWillUnmount")
}, [])

componentDidUpdate와 같은 역할

useEffect(() => {
	console.log("componentDidMount")
	console.log("componentDidUpdate") // + shouldComponentUpdate
	return () => console.log("???")
}, [state])

componentWillUnmount와 같은 역할

useEffect(() => {
	console.log("componentDidMount")
	return () => console.log("componentWillUnmount")
}, [])

CDM은 안하고 CDU만 하고 싶을때

cosnt [isMounted,setIsMounted] = useState(false);

useEffect(() =>{
	if(!isMounted) {
    console.log("CDM")
      setIsMounted(true)
      return
    }
  console.log("CDU")
})

clear 함수

profile
React, React-Native Developer

0개의 댓글