리액트 HOOKS

리린·2021년 7월 12일
0

React

목록 보기
4/47

(내가 보려고 씀)

useState

  • 요약: name과 setName을 사용하여 상태를 바꿀 수 있다.
  • 기술1: input의 value에 이 useState를 사용하여 라우터 잇기 편하게 하기

useEffect

  • 요약: 클래스형 컴포넌트-라이프사이클 메서드의 componentDidMount와 componentDidUpdate 의 역할을 한다
  • useState와 useEffect의 코드
import React, { useEffect, useState } from "react";
const Info = () => {
  const [name, setName] = useState("");
  const [nickname, setNickname] = useState("");
  useEffect(() => {
    console.log("effect");
    console.log(name);
    return () => {
      console.log("cleanup");
      console.log(name);
    };
  });
  const onChangeName = (e) => {
    setName(e.target.value);
  };
  const onChangeNickname = (e) => {
    setNickname(e.target.value);
  };
  return (
    <div>
      <div>
        <input value={name} onChange={onChangeName} />
        <input value={nickname} onChange={onChangeNickname} />
      </div>
      <div>
        <div>
          <b>이름: </b>
          {name}
        </div>
        <div>
          <b>닉네임: </b>
          {nickname}
        </div>
      </div>
    </div>
  );
};

export default Info;

useReducer

  • 요약: useState와 비슷하나 reducer함수를 따로 사용하여 경우에 따라 빼놓는다는 점이 다르다. 이때 dispatch 함수를 사용할 수 있는데, 인자로는 action 객체가 들어간다
  • 기술1: input의 value에 이 useReducer, 특히 onChange 메서드에 dispatch(e.target)를 사용하여 라우터 잇기 편하게 하기
  • 코드
import React, { useReducer } from "react";
function reducer(state, action) {
  return {
    ...state,
    [action.name]: action.value,
  };
}
const Info = () => {
  const [state, dispatch] = useReducer(reducer, {
    name: "",
    nickname: "",
  });
  const { name, nickname } = state;
  const onChange = (e) => {
    dispatch(e.target);
  };
  return (
    <div>
      <div>
        <input name="name" value={name} onChange={onChange} />
        <input name="nickname" value={nickname} onChange={onChange} />
      </div>
      <div>
        <b>이름: </b>
        {name}
      </div>
      <div>
        <b>닉네임: </b>
        {nickname}
      </div>
    </div>
  );
};
export default Info;

useMemo

  • 설명:
  • 요약: 컴포넌트 내부에서 발생하는 연산 최적화하기
  • 문제상황: 단순히 input에 값을 입력하는 '중'인데도 평균값을 계산하고 있음.
import React, { useState } from "react";

const getAverage = (numbers) => {
  console.log("평균값 계산 중...");
  if (numbers.length === 0) return 0;
  const sum = numbers.reduce((a, b) => a + b);
  return sum / numbers.length;
};
const Average = () => {
  const [list, setList] = useState([]);
  const [number, setNumber] = useState("");

  const onChange = (e) => {
    setNumber(e.target.value);
  };
  const onInsert = (e) => {
    const nextList = list.concat(parseInt(number));
    setList(nextList);
    setNumber("");
  };
  return (
    <div>
      <input value={number} onChange={onChange} />
      <button onClick={onInsert}>등록</button>
      <ul>
        {list.map((value, index) => (
          <li key={index}>{value}</li>
        ))}
      </ul>
      <div>
        <b>평균값:</b>
        {getAverage(list)}
      </div>
    </div>
  );
};

export default Average;
  • 해결방법: useMemo를 사용하면 된다.
  • useMemo의 첫 번째 인자에는 최적화할 함수(연산 포함)이, 두 번째 인자에는 관찰대상 배열이 온다. 이 관찰대상 배열 값(들)이 바뀔 경우에만 첫 번째 인자를 실행시킨다
  • 기술1:
  • 코드
import React, { useState, useMemo } from "react";

const getAverage = (numbers) => {
  console.log("평균값 계산 중...");
  if (numbers.length === 0) return 0;
  const sum = numbers.reduce((a, b) => a + b);
  return sum / numbers.length;
};
const Average = () => {
  const [list, setList] = useState([]);
  const [number, setNumber] = useState("");

  const onChange = (e) => {
    setNumber(e.target.value);
  };
  const onInsert = (e) => {
    const nextList = list.concat(parseInt(number));
    setList(nextList);
    setNumber("");
  };
  const avg = useMemo(() => getAverage(list), [list]);
  return (
    <div>
      <input value={number} onChange={onChange} />
      <button onClick={onInsert}>등록</button>
      <ul>
        {list.map((value, index) => (
          <li key={index}>{value}</li>
        ))}
      </ul>
      <div>
        <b>평균값:</b>
        {avg}
      </div>
    </div>
  );
};

export default Average;

useCallback

  • 설명
  • 요약: onChange 등 함수의 최적화를 해준다(리랜더링될 때마다 새로 만들어진 함수를 사용하게 되는데, 대개 괜찮지만 컴포넌트 렌더링이 자주 발생할 경우 필요하다)
  • 첫 번째 인자에는 생성하고 싶은 함수를, 두 번째 인자에는 관찰대상 값을 나열한 배열을 넣는다
  • 팁1: 두 번째 인자에 빈 배열을 넣을 경우 컴포넌트가 렌더링될 때 만들었던 함수를 계속해서 재사용함
  • 팁2: 함수 내부에서 조회하는 값은 필수로 두 번째 인자에 넣어줘야 함
  • 코드
import React, { useState, useMemo, useCallback } from "react";

const getAverage = (numbers) => {
  console.log("평균값 계산 중...");
  if (numbers.length === 0) return 0;
  const sum = numbers.reduce((a, b) => a + b);
  return sum / numbers.length;
};
const Average = () => {
  const [list, setList] = useState([]);
  const [number, setNumber] = useState("");

  const onChange = useCallback((e) => {
    setNumber(e.target.value);
  }, []); //컴포넌트가 처음 렌더링될 때만 함수 생성

  const onInsert = useCallback(
    (e) => {
      const nextList = list.concat(parseInt(number));
      setList(nextList);
      setNumber("");
    },
    [number, list]
  ); //number 혹은 list가 바뀌었을 때만 함수 생성
  const avg = useMemo(() => getAverage(list), [list]);
  return (
    <div>
      <input value={number} onChange={onChange} />
      <button onClick={onInsert}>등록</button>
      <ul>
        {list.map((value, index) => (
          <li key={index}>{value}</li>
        ))}
      </ul>
      <div>
        <b>평균값:</b>
        {avg}
      </div>
    </div>
  );
};
export default Average;

useRef

  • 설명
  • 요약: 함수형 컴포넌트에서 ref를 쉽게 사용할 수 있도록 해준다(참고로 이 ref는 렌더링 필요없이 바로 조회 가능하다. ref값이 바뀐다고 렌더링이 되진 않는다)
  • 코드
import React, { useState, useMemo, useCallback, useRef } from "react";

const getAverage = (numbers) => {
  console.log("평균값 계산 중...");
  if (numbers.length === 0) return 0;
  const sum = numbers.reduce((a, b) => a + b);
  return sum / numbers.length;
};
const Average = () => {
  const [list, setList] = useState([]);
  const [number, setNumber] = useState("");
  const inputEl = useRef(null);

  const onChange = useCallback((e) => {
    setNumber(e.target.value);
  }, []); //컴포넌트가 처음 렌더링될 때만 함수 생성

  const onInsert = useCallback(
    (e) => {
      const nextList = list.concat(parseInt(number));
      setList(nextList);
      setNumber("");
      inputEl.current.focus();
    },
    [number, list]
  ); //number 혹은 list가 바뀌었을 때만 함수 생성
  const avg = useMemo(() => getAverage(list), [list]);
  return (
    <div>
      <input value={number} onChange={onChange} ref={inputEl} />
      <button onClick={onInsert}>등록</button>
      <ul>
        {list.map((value, index) => (
          <li key={index}>{value}</li>
        ))}
      </ul>
      <div>
        <b>평균값:</b>
        {avg}
      </div>
    </div>
  );
};

export default Average;

*로컬 변수(렌더링과 상관없이 바뀔 수 있는 값) 사용시에도 useRef사용 가능

커스텀 hooks만들기

헷갈리는 메서드들

  1. .reduce
  • 설명
  • 배열.reduce((누적값, 현잿값, 인덱스, 요소) => { return 결과 }, 초깃값);
  • 초깃값 설정 안했을 경우 0이 기본임.
  1. .map
  • 설명
  • 배열.map((요소, 인덱스, 배열) => { return 요소 });
  1. .concat
  • 설명
  • 배열.concat(배열 혹은 값 )
  • 배열과 배열(혹은 값)을 값끼리 합쳐 나열한 배열을 반환
profile
개발자지망생

0개의 댓글