IT_susu

hook 종류들 본문

[ javascript ]/react

hook 종류들

고베베 2019. 6. 15. 13:02

1. useState

useState는 state를 설정해 주는 함수입니다.

const [count, setCount] = useState(0);

setCount(count++);

useState의 인자값에 state의 기본값을 넣어줄 수 있으며, 첫번째 변수는 state 변수, 두번째는 이 state를 제어하는 함수(세터함수)입니다.

 

기존의 state는 꼭 객체형식이어야 했고, this.setState는 기존의 state값들과 바뀐 값을 합쳤다면, useState는 객체가 아니어도 되며, 기존의 state들과 값을 병합하지 않고 대체합니다.

 

 

2. useEffect

side effect 작업들을 도와주는 함수.

componentDidMount, componentDidUpdate, componentWillUnmount를 하나로 합친 것입니다.

 

2-1 마운트 될때만 실행하고 싶을 때

componentDidMount 효과. 업데이트에서는 실행하지 않고 싶을 때, 두번째 파라미터에 빈 배열을 넣어주면 된다.

 useEffect(() => {
    console.log('마운트 될 때만 실행됩니다.');
  }, []);

2-2 업데이트 될때만 실행하고 싶을 때

componentDidUpdate 효과. 두번째 파라미터에 검사하고 싶은 값을 넣어주면 된다.

 useEffect(() => {
    console.log(name);
  }, [name]);

 

2-3 뒷정리 함수

컴포넌트가 언마운트 되기 전, 업데이트 되기 직전에 호출하는 함수이다. 

return 값을 넘겨주는 형태로 사용하며, componentDidUnmount 처럼 언마운트 시에만 사용하고 싶다면 두번째 파라미터로 빈 배열을 넣어준다.

useEffect(() => {
    console.log('effect');
    console.log(name);
    return () => {
      console.log('cleanup');
      console.log(name);
    };
  });

 

3. useMemo

useMemo가 무엇인지 찾아봤을 때, 이 것은 기존의 shouldComponentUpdate와 비슷하다는 느낌을 받았습니다.

최적화에 사용되며, 

방법은 두번째 인자에 배열로 전달한 상태값이 바뀔 떄만 재호출됩니다.

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;

 

4. useContext

contextAPI 같은 것처럼 전역적으로 사용하고자 할 때 쓰는 것 같습니다.

//ContextSample.js

import React, { createContext, useContext } from 'react';

const ThemeContext = createContext('black');
const ContextSample = () => {
  const theme = useContext(ThemeContext);
  const style = {
    width: '24px',
    height: '24px',
    background: theme
  };
  return <div style={style} />;
};

export default ContextSample;

 

5. useReducer

useReducer는 useState를 좀 더 자유롭게(?) 사용하는 방법입니다.

 const [state, dispatch] = useReducer(reducer, { value: 0 });

우선, useReducer의 형태는 위와 같이 생겼고 useReducer의 첫번째 인자로 action값을 담은 reducer 함수를 넣어주고, 두 번째 인자로 관리할 state값을 넣어줍니다.

그러면 state 변수에는 value:0이라는 객체가 담길 것이고, dispatch에는 액션을 발생시키는 함수(reducer)가 들어갑니다.

마치, useState의 state값 설정과 setState 쌍으로 작성하는 것과 비슷하게 생겼죠?

 

그럼 reducer라는 함수를 통해 어떻게 setState보다 더 자유롭게 사용하는지 살펴봅시다.

import React, { useReducer } from 'react';

function reducer(state, action) {
  // action.type 에 따라 다른 작업 수행
  switch (action.type) {
    case 'INCREMENT':
      return { value: state.value + 1 };
    case 'DECREMENT':
      return { value: state.value - 1 };
    default:
      // 아무것도 해당되지 않을 때 기존 상태 반환
      return state;
  }
}

const Counter = () => {
  const [state, dispatch] = useReducer(reducer, { value: 0 });

  return (
    <div>
      <p>
        현재 카운터 값은 <b>{state.value}</b> 입니다.
      </p>
      <button onClick={() => dispatch({ type: 'INCREMENT' })}>+1</button>
      <button onClick={() => dispatch({ type: 'DECREMENT' })}>-1</button>
    </div>
  );
};

export default Counter;

리듀서는 현재 상태와, 업데이트를 위해 필요한 정보를 담은 액션(action) 값을 전달 받아 새로운 상태를 반환하는 함수입니다. 리듀서 함수에서 새로운 상태를 만들 때는 꼭 불변성을 지켜주어야 합니다.

리듀서 함수는 리덕스와 달리 꼭 action에 type값으로 넘길필요는 없습니다.

 

5. useCallback

useCallback 은 결국 useMemo 에서 함수를 반환하는 상황에서 더 편하게 사용 할 수 있는 Hook 입니다. 숫자, 문자열, 객체 처럼 일반 값을 재사용하기 위해서는 useMemo 를, 그리고 함수를 재사용 하기 위해서는 useCallback 을 사용하세요.

useCallback(() => {
  console.log('hello world!');
}, [])

useMemo(() => {
  const fn = () => {
    console.log('hello world!');
  };
  return fn;
}, [])

 

6. useRef

1) dom 선택하기

import React, { useState, useMemo, 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;

2) 렌더링과 관련없는 값(로컬변수) 관리하기

import React, { useRef } from 'react';

const RefSample = () => {
  const id = useRef(1);
  const setId = (n) => {
    id.current = n;
  }
  const printId = () => {
    console.log(id.current);
  }
  return (
    <div>
      refsample
    </div>
  );
};

export default RefSample;

 

'[ javascript ] > react' 카테고리의 다른 글

event  (0) 2019.08.06
Ref  (0) 2019.08.06
hook - hook으로 인한 변화들  (0) 2019.06.15
모던 프론트엔드개발환경과 기존 환경과의 차이점  (0) 2019.05.14
react로 생각하기  (0) 2019.05.04
Comments