React

[새싹 프론트엔드] Hooks정리(1) : useState, useEffect, useRef

hyriver(강화영) 2022. 12. 11. 23:15

Hooks란?

리액트 버전 16.8에 새로 도입된 기능으로 클래스형 컴포넌트를 사용하지 않고 함수형 컴포넌트에서 상태 관리(성능 최적화)를 할 수 있다.

- 컴포넌트로부터 상태 관련 로직을 추상화할 수 있다 -> 코드 재사용 가능

 

 

 

1. useState

: 상태를 관리해야하는 사항이 있을 때 사용

해당 사항의 관리에 대한 변수와 해당 변수의 값을 변경 할 수 있는 함수가 있다

const [state, setState] = useState(0);            (괄호 안에는 state의 초기값)

 

 

* 여러개의 input값을 변경하기

import React, { useState } from "react";

//input의 값들을 state 객체의 키로 만들어서 묶어준다.
const Prac = () => {
  const [state, setState] = useState({
    maker: "",
    feelings: "",
  });

  //input창에 입력 시 값이 변하면 기존 state 객체는 그대로 가고(...state : 스프레드 연산자)
  //변하는 값만 '[키]:값'으로 새로 저장해준다
  const handleChangeState = (e) => {
    setState({
      ...state,
      [e.target.name]: e.target.value,
      // 객체의 키는 []로 사용한다
    });
  };

  return (
    <div className="Editor">
      <div>
        <input value={state.maker} name="maker" onChange={handleChangeState} />
      </div>
      <div>
        <textarea
          value={state.feelings}
          name="feelings"
          onChange={handleChangeState}
        />
      </div>
      <div>
        <p>만든이 : {state.maker}</p>
        <p>느낀점 : {state.feelings}</p>
      </div>
    </div>
  );
};

export default Prac;

상태변화 state를 객체로 만들어주고, 상태가 변하는 input이 여러개이므로 input의 name을 객체의 key로 설정한다.

input에는 onChange이벤트를 거는데, handleChangeState라는 함수를 실행시킨다.

handleChangeState는 앞에서 만든 객체 state의 상태를 변경시키는 setState를 수행하는 함수다.

input창을 입력하면 -> handleChangeState 함수가 수행되고 -> state 객체의 해당 키값이 변경되면서 상태를 변화시킨다

 

 

* setState() 인자에 초기값을 지정한 경우 state값이 업데이트 될 때마다 초기값이 계속 호출된다.

- 초기값에 복잡한 계산식이 있다면 성능 저하 문제 발생

- input이라면 input에 값을 입력할 때마다 초기값이 실행된다.

-> 해결방법 : useState()의 인자로 콜백함수를 넣어준다.

const [name, setName] = useState( () => heavyWork() );

 

 

 

2. useEffect

: 리액트 컴포넌트가 렌더링 될 때마다 특정 작업을 수행하도록 설정해주는 Hook

최초 한번 실행하게 하고 싶은 작업을 작성할 때 주로 사용     ex) 데이터 연결하는 작업

 

1) useEffect()의 매개변수에 콜백함수만 있는 경우(매개변수 1개)

useEffect( () => {} )

컴포넌트가 렌더링 될 때마다 실행 -> 이렇게 쓸 경우 사용하는 의미 없음..

ex) 네트워크 통신으로 데이터를 가져와야할 경우 계속 데이터를 새로 가져온다

 

2) useEffect()의 매개변수에 콜백함수, 배열이 있는 경우(매개변수 2개)

- 컴포넌트가 처음 렌더링 될 때만 실행 : 비어있는 배열이 들어갔을 때

-> 최초 한번만 콜백 함수를 실행 = mount될 때만 실행

useEffect( () => {}, [ ] )

 

- value 값이 변경 되었을 때 실행 : 배열안에 value가 들어갔을 때

useEffect( () => {}, [value] )

 

 

* cleanup : 컴포넌트가 update되기 직전 또는 unmout되기 직전에 어떠한 작업을 수행하고 싶다면

뒷정리(cleanup) 작업을 해줘야 한다.

-> useEffect() 함수 내부에서 return 함수를 반환

 

ex) DB연결 해제, 메모리 정리, 소켓 닫기 등

useEffect( () => { console.log("렌더링이 완료되었습니다.");

                            return () => { console.log("cleanup"); } }, [names] )

 

 

 

3. useRef()

: 컴포넌트 내부에서 사용되는 변수를 저장하는 Hook

특정 dom요소(html태그)에 접근 가능하여 객체(레퍼런스) 형식으로 관리할 수 있다.

 

1) useRef() 사용하여 값 저장하기

const ref = useRef(value)

useRef() 함수는 value 값으로 초기화된 ref 객체를 반환하는데

이 객체에는 current라는 키가 만들어지고 거기에 value가 저장된다.

-> { ref.current=value }

 

- ref 객체 값 변경 :  ref.current = "hello"

 

 

2) useRef()로 dom에 접근하기

import React, { useState, useRef } from "react";

const Editor = () => {
  //dom요소에 접근할 수 있는 useRef - 입력 되지 않았을 때 focus되도록
  //useRef로 makerInput이라는 객체를 만든다
  const makerInput = useRef();

  //객체 state의 값을 변경하는 useState
  const [state, setState] = useState({
    maker: "",
  });

  //입력창의 값이 변경되었을 경우 setState 함수를 사용하여 state 객체의 해당 키 값을 변경
  const handleChangeState = (e) => {
    setState({
      ...state,
      [e.target.name]: e.target.value,
      // 객체의 키는 []로 사용한다
    });
  };

  //버튼 클릭 시 저장하는 함수 - 모든 input창에 입력해야 저장된다
  //ref={makerInput}로 input에 접근하면
  //makerInput.current 가 곧 input, 즉 input에 focus되도록
  const handleSubmit = () => {
    if (state.maker.length < 1) {
      alert("만든이를 입력해주세요");
      makerInput.current.focus();
      return;
    }
  };

  return (
    <div className="Editor">
      <div>
      {/* input안에 ref키의 값을 makerInput으로 지정 = input(dom객체)에 makerInput이 접근 */}
        <input
          value={state.maker}
          ref={makerInput}
          name="maker"
          onChange={handleChangeState}
        />
      </div>

      <button onClick={handleSubmit}>저장하기</button>
    </div>
  );
};

export default Editor;

input창을 입력하지 않고 저장하기 버튼을 누를경우 alert가 뜨도록 한다.

makerInput이라는 useRef를 만들고 input 속성으로 ref를 makerInput으로 지정한다.

-> makerInput은 input에 접근한 것이고 makerInput.current를 input처럼 사용해서 포커스를 줄 수 있다.

 

 

 

새싹DT 기업연계형 프론트엔드 실무 프로젝트 과정 8주차 블로그 포스팅