React Native 추가 Hook

silver·2021년 8월 1일
0

추가 Hook

이번엔 저번에 알아본 hook말고 다른 hook들에 대해 알아보도록 하겠다.

useReducer

const [state, dispatch] = useReducer(reducer, initalArg, init);
  • useState의 대체 함수
  • (state, action) => newState의 형태로 reducer를 받고 dispatch메서드와 짝의 형태로 현재 state를 반환
  • useState보다 useReducer를 선호하는 경우
    • 다음 state가 이전 state에 의존적
    • 다수의 하윗값을 포함하는 복잡한 정적 로직
  • 콜백 대신 dispatch를 전달
  • 예제
const initialState = {counst: 0};

function reducer(state, action) {
  switch(action.type) {
    case 'increment':
      return {count: state.count + 1};
    case 'decrement':
      return {count: state.count - 1};
    default:
      throw new Error();
  }
}

function Counter() {
  count [state, dispatch] = useReducer(reducer, initialState);
  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
    </>
  );
}

주의
React는 dispatch 함수의 동일성이 안정적이고 리렌더링 시에도 변경되지 않으리라는 것을 보장

초기화 지연

  • 초기 state를 조금 지연해서 생성 가능
    -> init함수를 세번째 인자로 전달
  • 초기 state는 init(initialArg)에 설정됨
  • reducer 외부에서 초기 state를 계산하는 로직을 추출할 수 있도록 함
  • 어떤 행동에 대한 대응으로 나중에 state를 재설정하는 데 유용
function init(initialCount) {
  return {count: initialCount};
}

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return {count: state.count + 1};
    case 'decrement':
      return {count: state.count -1 };
    case 'reset':
      return init(action.payload);
    default:
      throw new Error();
  }
}

function Counter({initialCount}) {
  const [state, dispatch] = useRedcuer(reducer, initialCount, init);
  return (
    <>
      Count: {state.count}
      <button
        onClick={() => dispatch({type: 'reset', payload: initialCount})}>
        Reset
      </button>
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
    </>
  );
}

dispatch의 회피

  • reducer hook에서 현재 state와 같은 값을 반환 하는 경우
    -> react는 자식을 리렌더링하거나 effect를 발생하지 않고 회피 (object.is비교 알고리즘 사용)

useCallback

const memoizedCallback = useCallback(
  () => {
    doSomething(a,b);
  },
  [a, b],
);

메모이제이션된 콜백을 반환

  • useCallback은 콜백의 메모이제이션되 버전을 반환
  • 메모이제이션된 버전은 콜백의 의존성이 변경되었을때에만 변경
  • useCallback(fn, deps)useMemo(() => fn, deps)와 동일

주의
의존성 값의 배열이 콜백에 인자로 전달되지 않음

useMemo

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

메모이제이션된 값을 반환

  • "생성(create)"함수와 그것의 의존성 값의 배열을 전달
  • useMemo는 의존성이 변경되었을 때에만 메모이제이션된 값만 다시 계산
  • useMemo로 전달된 함수는 렌더링 중에 실행
  • 배열이 없을 경우 매 렌더링 때마다 새 값을 계산
  • useMemo는 성능 최적화 위해 사용 가능, 하지만 이것이 보장된다는 것은 아님
    • 메모이제이션된 값들의 일부를 "잊어버리고" 다음 렌더링시 재계산 가능
    • ex) 오프스크린 컴포넌트의 메모리 해제
  • useMemo를 사용하지 않도고 동작할 수 있도록 코드를 작성

주의
의존성 값의 배열은 함수에 인자로 전달되지 않음

useRef

const refContainer = useRef(initialValue);
  • useRef.current 프로퍼티로 전달된 인자(initialValue)로 초기화된 변경 가능한 ref객체를 반환
  • 반환된 객체는 컴포넌트의 전 life cycle를 통해 유지
  • 일반적 use case
    • 자식에게 명령적으로 접근하는 경우
function TextInputWithFocusButton() {
  const inputE1 = useRef(null);
  const onButtonClick = () => {
    //`current` points to the mounted text input element
    inputE1.current.focus();
  };
  
  return (
    <>
      <input ref={inputE1} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </>
  );
}

useRef.current 프로퍼티에 변경 가능한 값을 담고 있는 "상자"와 같다.

  • useRef() 순수 자바스크립트 객체 생성
  • useRef는 매변 렌더링시 동일한 ref 객체를 제공
  • useRef는 내용이 변경될때 알려주지 않음
  • .current 프로퍼티를 변형하는 것이 렌더링을 발생시키진 않음
  • DOM 노드에 ref를 attach/detach할 때 어떤 코드를 실해시키고 싶을 경우
    -> callback ref를 사용

useImperativeHandle

useImperativeHandle(ref, createHandle, [deps])
  • useImperativeHandleref를 사용할 때 부모 컴포넌트에 노출되는 인스턴 값을 사용자화함
  • useInmperativeHandleforwardRef와 더불어 사용
function FancyInput(props, ref) {
  const inputRef = useRef();
  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    }
  }));
  return <input ref={inputRef} ... />;
}
FancyInput = forwardRef(FancyInput);
  • <FancyInput ref={inputRef}/>를 렌더링한 부모 컴포넌트는 inputRef.current.focus()를 호출 가능

useLayoutEffect

  • useEffect와 시그니처 동일
  • 모든 DOM 변경 후 동기적으로 발생
  • 화면을 그리기 이전 시점에 동기적으로 수행
  • 화면 갱신 차단의 방지 가능할 경우 useEffect 먼저 사용

0개의 댓글