본문 바로가기

WEB/React

React Hooks

목차

 

hooks 등장배경은 생략

Hook의 등장배경을 이야기하는 글 몇 개를 읽어보고 그런가보다 하고 넘어갔다. 결국 클래스형 컴포넌트에서 사용하던 state 나 라이프사이클 매서드를 함수형 컴포넌트에서 사용하기가 어려워서 등장한게 hook 인데, 클래스형 컴포넌트를 안 써봐서 뭐가 어떻게 불편했다는 건지 와닿지 않는다. 클래스형 컴포넌트 코드를 함수형으로 리팩토링해야될 상황을 만나기 전까지는 클래스형 컴포넌트가 뭔지 모를 예정 ㅋㅋ

velopert 의 리액트 튜토리얼을 참고했다.

 

useState

  • 가장 기본적인 hook이며 함수형 컴포넌트에서도 가변적인 state를 다룰 수 있게 해줌
const [message, setMessage] = useState(''); // 비구조화할당
const onClickEnter = () => setMessage('안녕하세요');
const onClickLeave = () => setMessage('안녕히가세요');
  • useState() 함수를 호출하면 배열이 반환된다. 배열의 첫 번째 원소는 원소의 현재상태, 두 번째 원소는 상태를 바꾸어주는 setter 함수이다.
  • state 값을 변경할 때는 직접 바꾸면 안되고, setter 함수를 사용해야 한다. (불변성을 지키기 위함)
  • 따라서 배열이나 객체를 업데이트해야 할 때는, 배열이나 객체의 사본을 만들고 -> 사본의 값을 없데이트한 후 -> setter 함수를 통해 갈아끼운다.
  • 보통 setter 함수에 업데이트할 값을 매개변수로 넣어주는 형태로 사용하지만, 아래의 예시처럼 값을 업데이트하는 함수를 넣어주는 형태로 사용할 수도 있다.
import React, { useState } from 'react';

const Counter = () => {
  const [number, setNumber] = useState(0);

  const onIncrease = () => {
    setNumber(prevNumber => prevNumber + 1);
  }
  const onDecrease = () => {
    setNumber(prevNumber => prevNumber - 1);
  }

  return (
    <div>
      <h1>{number}</h1>
      <button onClick={onIncrease}>+1</button>
      <button onClick={onDecrease}>-1</button>
    </div>
  );
};

export default Counter;
  • 관리해야할 상태가 여러개라면, 아래처럼 객체 형태로 만들어 객체의 상태를 관리하게 하는 것도 좋은 방법이다.
import React, { useState } from 'react';

const InputSample = () => {
  const [inputs, setInputs] = useState({
    name: '',
    nickname: ''
  });

  const { name, nickname } = inputs;

  const onChange = (e) => {
    const { value, name } = e.target;  // 현재 target에 해당하는 name과 value를 추출
    setInputs({
      ...inputs,
      [name]: value
    });
  }

  const onReset = () => {
    setInputs({
      name: '',
      nickname: ''
    });
  };

  return (
    <div>
      <input 
        name="name" 
        placeholder="이름" 
        onChange={onChange} 
        value={name} />
      <input 
       name="nickname" 
       placeholder="닉네임" 
       onChange={onChange} 
       value={nickname}/>
      <button onClick={onReset}>초기화</button>
      <div>
        <b>값: </b>
        {name} ({nickname})
      </div>
    </div>
  );
};

export default InputSample;

 

useEffect

  • 리액트 컴포넌트가 랜더링될 때마다 특정 작업을 수행하도록 할 수 있는 hook
  • useEffect 는 첫번째 파라미터에는 함수, 두번째 파라미터에는 의존값이 들어있는 배열 (주로 deps라고 칭함)을 넣는다.
  • 마운트 됐을 때 (처음 나타났을 때), 언마운트 됐을 때 (사라질 때), 그리고 업데이트 될 때 (특정 props가 바뀔 때) 로 구분해서 특정 작업을 처리하는 것이 가능하다.
  • 마운트 될 때만 실행되고 업데이트 될 때는 실행되지 않게 하려면 useEffect()의 두번째 인자로 빈 배열(, []) 넘기면 됨.
useEffect(() => {
  console.log('컴포넌트가 화면에 나타남');
}, []);
  • 언마운트 될 때만 호출하고 싶다면 return 문으로 cleanup 함수를 반환해주고, 두번째 인자로 빈 배열을 넘기면 됨.
  • cleanup 함수는 useEffect 의 뒷정리 함수라고 생각하면 된다. 
useEffect(() => {
  console.log('컴포넌트가 화면에 나타남');
  return () => {
    console.log('컴포넌트가 화면에서 사라짐');
  };
}, []);
  • 특정 변수가 업데이트 될 때마다 실행하고 싶다면, 두번째 인자로 해당 변수들 넘겨주면 됨.(, [user])
  • 이렇게 하면 마운트 될 때도 실행되고, 특정값이 업데이트 될 때도 실행된다.
  • cleanup 함수는 컴포넌트가 언마운트될 때도 실행되고 특정 변수가 업데이트될 때도 실행된다.
useEffect(() => {
  console.log('user 값이 설정됨');
  console.log(user);
  return () => {
    console.log('user 가 바뀌기 전..');
    console.log(user);
  };
}, [user]);
  • 두번째 인자를 아예 생략하면 컴포넌트가 리렌더링 될 때 마다 실행된다.
    • 리액트는 기본적으로 부모컴포넌트가 리렌더링되면, 자식 컴포넌트도 리렌더링 된다. (바뀐값이 없어도)
    • deps에 값을 넣는것을 기본이라고 생각하는게 좋다.

useRef

  • javascript 에서 getElementById, querySelector 로 DOM 을 선택하듯이 useRef 를 이용해 DOM을 선택할 수 있다.
  • useRef() 는 .current 프로퍼티가 useRef 의 매개변수로 초기화된 변경가능한 ref 객체를 반환한다.
  • 특정 input 태그에 포커스 주기 / 스크롤 박스 조작하기 / Canvas 요소에 그림그리기 등 DOM 요소에 직접 접근해 어떤 작업을 하기 위해 DOM에 이름을 다는 것이다. (chart.js 와 같은 외부 라이브러리 적용할 때도 유용하다)
//...

const nameInput = useRef();

const onClick = () => {
  nameInput.current.focus();
}

return(
  <input ref={nameInput} />
  <button onClick={onClick}>클릭</button>
)

//...
  • ref 는 전역으로 작동하지 않고 컴포넌트 내부에서만 작동하므로 중복을 걱정하지 않아도 된다.
  • 따라서 컴포넌트 로컬 변수를 사용해야할 때도 useRef를 활용할 수 있다.
  • 로컬 변수는 렌더링과 상관없이 바뀔 수 있는 값을 의미한다. 리액트 컴포넌트에서의 상태는 상태를 바꾸는 함수를 호출하고 나서 그 다음 렌더링 이후로 업데이트 된 상태를 조회 할 수 있는 반면, useRef 로 관리하고 있는 변수는 설정 후 바로 조회 할 수 있다.
  • useRef() 에 매개변수를 넣어주면 이 값이 .current의 초기값이 된다. 조회할 때는 .current 를 조회하면 된다.
const nextId = useRef(4);
const onCreate = () => {
  // ...

  nextId.current += 1;
};

 

 

 

작성중..

'WEB > React' 카테고리의 다른 글

Why React ?  (0) 2021.05.19