Skip to content
uihyeon.cha edited this page Mar 6, 2020 · 5 revisions

이 프로젝트는 React Hook을 학습하기 위해 의도적으로 React Function Component만 사용하였습니다. Hook API는 React 16.8부터 사용할 수 있습니다.

Hook API에 대한 자세한 설명은 React Hook 가이드를 참고해주세요.

React Component에서 StateLifecycle을 사용하려면 Class Component를 사용해야 했지만 Hook API의 추가로 Function Component에서도 State를 사용할 수 있게 되었습니다.

Lifecycle은 전부 사용할 수는 없고 componentDidMount, componentWillUnmount를 유사하게 구현할 수 있습니다.

useRef

const refContainer = useRef(initialValue)
// refContainer.current === initialValue

useRefinitialValue로 전달된 값을 current라는 프로퍼티에 저장하고 변경가능한 순수 자바스크립트 객체를 반환합니다. Function Component 안에서 작성한 변수는 렌더링 될 때마다 초기화되는데, useRef를 사용하면 동일한 객체가 유지됩니다. useRef로 생성된 객체는 값을 변경해도 리렌더링되지 않습니다.

function TextInputWithFocusButton() {
  const inputEl = useRef(null)
  const onButtonClick = () => {
    inputEl.current.focus()
  }
  return (
    <div>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </div>
  )
}

위 예제 출처 : https://ko.reactjs.org/docs/hooks-reference.html#useref

useState

const [state, setState] = useState(initialState)

useState는 상태 값과 그 값을 갱신하는 함수를 반환합니다. initialState는 상태 값의 초기 값으로 사용되며 최초 렌더링에서만 사용됩니다.

import React, { useState } from 'react'

function Example() {
  // "count"라는 새로운 상태 값을 정의합니다.
  const [count, setCount] = useState(0)

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  )
}

위 예제 출처 : https://ko.reactjs.org/docs/hooks-intro.html

주의사항으로 Class Component의 setState와 다르게 이전 객체와 갱신 객체를 자동으로 합쳐주지 않습니다.

setState(prevState => {
  return {...prevState, ...updatedValues}
})

위 예제 출처 : https://ko.reactjs.org/docs/hooks-reference.html#usestate

useEffect

useEffect(effect: React.EffectCallback, deps?: React.DependencyList | undefined): void

StateProps가 변경되었을 때 effect 인자에 입력한 Callback 함수를 실행합니다. 얼핏 보면 componentDidUpdate와 비슷해 보이지만 useEffect는 브라우저가 화면을 다 그릴 때까지 Callback 함수 실행을 지연시킵니다.

useEffect(() => {
  state.hasMapData && methods.calcMapSize()
}, [state.hasMapData])

https://github.com/divlook/ladder-game/blob/ec760ee870eaa32d364810c9f481dae01ef6d583/components/LadderGame.tsx#L189-L191

특정 값이 변경될 때만 useEffect를 사용하고 싶다면 두번째 인자인 deps에 의존성을 추가하시면 됩니다.

useEffectstate.hasMapData이 변경될 때만 Callback 함수를 실행합니다.

useEffect(() => {
  methods.paintLadder()
  window.addEventListener('resize', methods.handleWindowResize)

  return () => {
      window.removeEventListener('resize', methods.handleWindowResize)
  }
}, [])

https://github.com/divlook/ladder-game/blob/ec760ee870eaa32d364810c9f481dae01ef6d583/components/LadderGame.tsx#L180-L187

만약 useEffect를 첫번째 렌더링에서만 사용하고 싶다면 deps[] 빈 배열을 입력하시면 됩니다. 의존성이 없기때문에 컴포넌트가 mount 되거나 unmount 할 때 실행되게 됩니다. 그리고 effect 함수 내의 PropsState는 초기 값이 유지되므로 주의하셔야됩니다.

useEffecteffect 함수 내에서 함수를 return하여 clean-up 함수를 만들 수 있습니다. clean-up 함수는 컴포넌트가 제거되거나 재렌더링으로 인해 effect 함수가 다시 실행될 때 실행됩니다.

useReducer

const [state, dispatch] = useReducer(reducer, initialState)
const [state, dispatch] = useReducer(reducer, initialArguments, initializer)

useReduceruseState의 대체 함수입니다. 다수의 하윗값을 포함하는 복잡한 객체나 다음 state가 이전 state에 의존적인 경우에 보통 useState보다 useReducer를 선호합니다.

https://ko.reactjs.org/docs/hooks-reference.html#usereducer

아래는 useReducer의 예제입니다.

const CHANGE_NAME = 'CHANGE_NAME'

const initialState = {
    playerName: '',
}

const actions = {
  changeName: (playerName: string) => {
    return {
        type: CHANGE_NAME,
        payload: {
            playerName,
        },
    }
  }
}

const reducer = (state = initialState, action) => {
  switch (action.type) {
    case CHANGE_NAME: {
      state.playerName = action.payload.playerName
      return state
    }

    default: {
      throw new Error()
    }
  }
}

const ExamplePage: NextPage = () => {
  const [store, dispatch] = useReducer(IndexReducer, initialState)
  const changeName = e => {
    dispatch(actions.changeName(e.target.value))
  }
  return (
    <DefaultLayout>
      <Text>{store.playerName}</Text>
      <TextField onChange={changeName} />
    </DefaultLayout>
  )
}

https://github.com/divlook/ladder-game/blob/v0.1.3/reducers/index.type.ts
https://github.com/divlook/ladder-game/blob/v0.1.3/reducers/index.action.ts
https://github.com/divlook/ladder-game/blob/v0.1.3/reducers/index.reducer.ts
https://github.com/divlook/ladder-game/blob/v0.1.3/pages/index.tsx

useCallback

useCallback(callback: T, deps: React.DependencyList): T
const memoizedCallback = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b],
)

예제 출처 : https://ko.reactjs.org/docs/hooks-reference.html#usecallback

useCallback메모이제이션된 콜백을 반환합니다. Function Component 내에서 선언된 콜백 함수를 자식 컴포넌트에게 전달할 때 useCallback을 사용하지 않으면 부모 컴포넌트의 재렌더링 여부와 상관없이 자식 컴포넌트는 Props 변경되어 계속해서 재렌더링 될 것입니다. useCallback은 의존성(deps) 값이 변경되지 않으면 동일한 값을 참조하여 자식 컴포넌트의 불필요한 재렌더링을 방지할 수 있습니다.

Link

Wiki

미리보기

소개 및 기술 스택

Guides

Project Structure
프로젝트 구조

Installation
설치

Settings
설정

Commands
명령어들

Deployment
배포

Page rules
페이지 규칙

React Hooks API

Review

Beta (v0.1.3)

Clone this wiki locally