React

[React] Hooks 알아보기 ( useState , useEffect )

김채연채연 2023. 6. 23. 17:18

함수 앞에 use 를 붙여 리액트에서 낚아서 슬 수 있도록 만든걸 react hooks 라고 부른다.

함수형 컴포넌트가 클래스형 컴포넌트같은 기능을 할 수 있게 해준다.

useState

class 컴포넌트로 state 를 활용해서 만들것이다.

import React from 'react';

export default class Example1 extends React.Component {
  state = {count : 0};

  render() {
    const {count} = this.state; //  state 는 객체

    return (
      <div>
        <p>
          You clicked {count} times
        </p>
        <button onClick={this.click}>Click me</button>
      </div>
    );
  }

  click = () => {
    this.setState({count: this.state.count + 1});
  }
}

이걸 function 컴포트로 변경하면

import React from "react";

export default  function Example2() {
  const [count , setCount] = React.useState(0);
  // 앞선 state = {count :0} 을 뽑아내서 변경될 수 있는 값으로 사용하는 것

  function click() {
    setCount(count + 1);
  }
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={click}>Click me</button>
    </div>
  );
}

→ function 컴포넌트에선 this 를 사용 x

둘 다 잘 나온다.

여기까지가 가장 기본적인 useState 를 활용하는 방법이다.

Example2 에서 useState 가 count 였다면 이번엔 객체로(useState : {count : 0} ) 받아볼 것이다.

import React from "react";

export default function Example3() {
  const [state, setState] = React.useState({ count: 0 });
  function click() {
    setState({count : state.count + 1});
  }
  return (
    <div>
      <p>You clicked {state.count} times</p>
      <button onClick={click}>Click me</button>
    </div>
  );
} 

여기서 setState 안에 함수로 넣을 수도 있다.

function click() {
    setState(state => ({
        count : state.count + 1,
    }));
  } 

useState 가 나오면서 Function Component가 더이상 Stateless Component 가 아니게 되었다.

왜 class 컴포넌트가 아닌 function 컴포넌트에서 상태성을 사용하려고 하느냐 ?

  • 컴포넌트 사이에서 상태와 관련 로직을 재사용 하기 어렵다.
  • 복잡한 컴포넌트들은 이해하기 어렵다.
  • class 는 사람과 기계를 혼동시킨다. (컴파일 단계에서 코드를 최적화하기 어렵게 만든다.)
  • this.state 는 로직에서 레퍼런스를 공유하기 때문에 문제가 발생할 수 있다.

useEffect

종류

  • → componentDidUpdate
  • →componentWillUnmount
  • → componentDidMount
import React from "react";

export default class Example4 extends React.Component {
  state = { count: 0 };

  render() {
    const { count } = this.state;

    return (
      <div>
        <p>You clicked {count} times</p>
        <button onClick={this.click}>Click me</button>
      </div>
    );
  }

  componentDidMount() {
    //최초의 랜더가 실행된 직후
    console.log('componentDidMount' , this.state.count);
  }

  componentDidUpdate() {
    console.log("componentDidUpdate", this.state.count);

  }

  click = () => {
    this.setState({ count: this.state.count + 1 });
  };
}

Example1 을 복사해서 사용한다.

저렇게 각각 DidMount 와 DidUpdate 를 콘솔로 출력해보면

이렇게 최초에 DidMount 가 한번 출력되고 그 이후로 DidUpdate 가 클릭할때마다 출력된다.

import React from "react";

export default function Example5() {
  const [count, setCount] = React.useState(0);
  // 앞선 state = {count :0} 을 뽑아내서 변경될 수 있는 값으로 사용하는 것

  React.useEffect(() => {
    console.log('componentDidMount & componentDidUpdate', count);
  }, []) // 두 상황 모두 실행되는 역할 

  function click() {
    setCount(count + 1);
  }
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={click}>Click me</button>
    </div>
  );
}

Example2 복사해서 사용

결국 componentDidMount 의 역할을 하는걸 볼 수 있다.

추가설명

React.useEffect(() => {
    console.log("componentDidMount ");

    return () => {
      //cleanup
      //이 위치가 componentWillUNmount 의 역할을 하고있다.
    }
  }, []); // 두 상황 모두 실행되는 역할 , 뒤에 배열은 실행되는 타이밍을 조절한다.
  // 빈 배열을 두면 최초에만 실행된다.
    React.useEffect(() => {
      console.log("componentDidMount & componentDidUpdate by count", count);
      return () => {
        console.log('cleanup by count', count);
      } // useEffect 가 실행되기 이전의값으로 return 부분을 실행한다.
      
      // 
    }, [count]);

우리는 위에서 useEffect 가 DidMount 의 역할을 하는것을 알아냈다. useEffect 내부에 return 값을 넣으면 전문용어로 “cleanup” 이라고 한다.

먼저, 매번 업데이트 되는 값을 넣기 위해 [] 안에 count 를 넣었다.

그리고 return 안에 count 와 밖의 괄호 안의 count 를 비교해보면

이렇게 나온다. 즉, return 내부는 useEffect 가 실행되기 이전의 값으로 실행되는걸 알 수 있다.