티스토리 뷰

Hook은 리엑트 v16.8에 추가된 기능이며, 함수형 컴포넌트에서 state와 생명주기와 같은 여러 기능을 제공하는 라이브러리 입니다. 

  • 최상위(at the Top Level)에서만 hook을 호출해야합니다.
    반복문, 조건문 또는 중첩된 함수 내에서 hook을 호출하면 안됩니다.
    early return(함수 또는 반복문 등에서 끝에서 return 되기 전 if문 안에서 일찍 return 하는 것)전에 항상 React함수의 최상위에 hook을 호출해야합니다. 
  • 오직 React 함수 내에서 hook을 호출해야 합니다.
import React, { useState } from "react"

function HookTest(props) {
  if (props.name == 'User') {
    const [name, setName] = useState('User'); // 오류: Hook 규칙 위반
  }
}

1. React Hook 내장 API

 

1. useState : 컴포넌트의 state(상태)를 관리합니다.
(클래스형 컴포넌트의 constructor()에서 state를 초기화하는 것과 비슷한 역할)

// useState의 사용 구조
const [사용할 state, state의 상태값을 설정하는 함수] = useState(state 초기값)


// 일반적인 useState의 사용
const [name, setName] = useState('User');
setName('UserChange'); //name을 UserChange로 바꿔줌.


// 여러개의 state를 한번에 관리하고자 할때 => prevState를 통해 관리
const [userInfo,setUserInfo] = useState({name:'User', email:'a@tistory.com', age:'28' });
setUserInfo(prevState=> {
     return {...prevState, name:'UserChange'}
}) //prevState에 userInfo 값들이 들어있고, 이를 통해 바꾸고자하는 name값만 UserChange로 바꿔줌.

 

 

2. useEffect : state값이 변경 될 때마다, 특정 기능이 동작하도록 관리합니다.
(클래스형 컴포넌트의 componentDidMount(), componentDidUpdate, componentWillUnmount() 것과 비슷한 역할)

// useEffect의 사용 구조 => []배열에 넣어준 state가 바뀔 때 마다 동작.
useEffect(() => {
   ~ 함수 로직 전개 ~
}, [state값])


// 1. 빈 배열은 구성 요소가 마운트 될 때마다 효과가 한 번만 실행되고 모든 다시 렌더링시 실행되지 않음을 의미
// componentdidMount
useEffect(() => {
   console.log('componentdidMount')
}, [])

// 2. 배열에 state값을 넣어주면 넣어준 state가 변화되면 실행
// componentdidUpdate
useEffect(() => {
   console.log('name Changed')
}, [name])

 

 

3. useContext : 여러개의 컴포넌트에서 사용 가능한, 변수 나 함수를 만들 수 있습니다.

(전역적 성질, 2중 3중으로 prop를 내려 주는 행위를 방지할 수 있음.)

// newContext.js
import { createContext } from "react"  // createContext 함수 불러오기

// context안에 homeText란 변수를 만들고, 공백("") 문자를 저장한다.
const newContext = createContext({
  homeText: "",
})


// Home.js
import React from "react";
import { Text, View } from "react-native";
import { useContext } from "react";
import { newContext } from "../newContext"; //newContext.js의 newContext를 불러옴

export default function Home() {

  // useContext hook 사용해서, newContext에 저장된 정보 가져오기
  const { homeText } = useContext(newContext);
  
  // 불러온 정보 사용하기!!
  return (
    <View>
      <Text>{homeText}<Text>
    </View>
  );
}

 

 

4. useReducer : useState()의 대체 함수로, 다양한 컴포넌트 상황에 따라 상태 값을 설정합니다.

const [state, dispatch] = useReducer(reducer, initialState, init);
// 첫 번째 인자로 현재 상태(state)와 행동(action)을 인자로 받는 reducer 함수를,
// 두 번째 인자로 상태의 초기값을
// 세 번째 인자로는 상태 초기화 함수를 넣고 현재 상태(state)와 액션을 발생시키는 함수(dispatch)를 반환

 

 

5.useCallback, useMemo

 5-1. useCallback()
  렌더링 최적화에 사용하며, 의존 배열에 있는 값이 변할 때만 첫 번째 인자로 주어진 콜백함수를 새로 생성하여 반환합니다.

const memoizedCallback = useCallback(callback, dependency);
// 두 번째 인자로 주어진 의존 배열(dependency)의 값이 바뀌면 
// 첫 번째 인자로 주어진 콜백함수(callback)를 새로 생성하여 반환

// ex) number의 값이 변할 때마다 number의 값에 1을 더해주는 함수를 기억하고있다가 클릭 이벤트가 발생할 경우 해당 함수를 실행
const onClick = useCallback(e => { e.preventDefault(); setNumber(number + 1); ), [number]};

 5-2. useMemo()
  연산 최적화에 사용하며, 의존 배열에 있는 값이 변할 때만 첫 번째 인자로 주어진 콜백함수를 실행하여 구한 값을 반환합니다.

const memoizedValue = useMemo(callback, dependency);
// 렌더링 과정에서 두 번째 인자로 받은 의존 배열(dependency)내 값이 바뀌는 경우에만
// 첫 번째 인자로 받은 콜백함수를 실행하여 구한 값을 반환하는 함수

// ex) 배열의 모든 요소 합을 구하는 함수 
const getSum = (arr) => { return arr.reduce((a, b) => a + b); } 
const arr = [1, 2, 3, 4]; 
const sum = useMemo(() => getSum(arr), [arr]);

=> useMemo()는 숫자 또는 문자열, 배열, 객체 등의 값을 반환하고 useCallback()은 함수를 반환한다는 점에서 차이가 있습니다.

 

 

6.useRef, useImperativeHandle

 6-1. useRef()

  ref를 쉽게 사용할 수 있도록 해주고, 컴포넌트나 Html 요소를 래퍼런스로 관리 가능합니다.

 6-2. useImperativeHandle()

  useRef로 만든 래퍼런스를 상위 컴포넌트로 전달할 수 있습니다. (상위 컴포넌트에서 하위 컴포넌트의 함수, 데이터 가져오기 가능)

// container.js
    const MainContainer = (props) => {
    
        const mainContent = useRef(); 
        
        return (
                <div>
                    <MainContent
                       ref={mainContent}
                    />
                </div>
            )
    };

// ref를 연결하면 하위 컴포넌트 MainContent에 접근이 가능
// mainContent.current.name
// mainContent.current.funcTest
// MainContent.js
// ref를 forwardRef 내부의 (props, ref) => ... 함수의 두 번째 인자로 전달
    const MainContent = forwardRef((props, ref) => {

        const [name, setName] = useState('User');

        let funcTest = () => {
            console.log('ref');
        }

        useImperativeHandle(ref, () => ({ //forwardRef와 같이 써야함.
            name: name,
            funcTest:funcTest
        }));


    });

 

 

 

useState, useEffect, useRef, useImperativeHandle 는 프로젝트에 직접 사용을 해보았고
useContext, useReducer, useCallback, useMemo 는 아직 사용을 못해보았다. 
사용하지 못한 hook 내장 API도 기회가 될 때 사용해보고 다시 정리해둬야겠다!

 

 

*참조
https://talking-potato.me/m/52

 

[React] 리액트 훅 💪

오늘을 리액트 훅에 대해 다루겠습니다. 리액트 훅(React Hooks)이란 리액트 16.8 버전부터 추가된 기능으로, 클래스 컴포넌트와 생명주기 메서드를 이용하여 작업을 하던 기존 방식에서 벗어나 함

talking-potato.me

댓글