Context api, redux, mobx, swr

홍성표·2022년 6월 7일
0

React 에는 전역상태를 관리하는 여러가지 라이브러리가 존재한다.
하나씩 알아보도록 하자.

Context api

  • 일반적인 React 애플리케이션에서 데이터는 위에서 아래로 (즉, 부모로부터 자식에게) props를 통해 전달되지만, 애플리케이션 안의 여러 컴포넌트들에 전해줘야 하는 props의 경우 (예를 들면 선호 로케일, UI 테마) 이 과정이 번거로울 수 있다.
  • context를 이용하면, 트리 단계마다 명시적으로 props를 넘겨주지 않아도 많은 컴포넌트가 이러한 값을 공유하도록 할 수 있다.

사용이 편리하지만 속도가 느리고 렌더 성능상의 이슈가 있다.

redux

  • Redux는 React 앱의 상태를 중앙 집중식으로 저장하고 관리하는데 사용되는 상태 관리 라이브러리이다.
  • Redux는 앱의 모든 상태를 하나의 전역화된 상태 객체로 추상화한다.

Redux의 세가지 원칙

  • 전체 상태 값이 하나의 자바스크립트 객체로 표현된다.
  • 상태 값은 읽기 전용의 불변 객체로 관리한다.
  • 오직 순수함수에 의해서만 상태값을 변경할 수 있다.

구조가 복잡하지만 자주 업데이트 되는 앱에서 효율적인 사용이 가능하다.

ex)

import { createStore } from 'redux'

/**
 * 이것이 (state, action) => state 형태의 순수 함수인 리듀서입니다.
 * 리듀서는 액션이 어떻게 상태를 다음 상태로 변경하는지 서술합니다.
 *
 * 상태의 모양은 당신 마음대로입니다: 기본형(primitive)일수도, 배열일수도, 객체일수도,
 * 심지어 Immutable.js 자료구조일수도 있습니다.  오직 중요한 점은 상태 객체를 변경해서는 안되며,
 * 상태가 바뀐다면 새로운 객체를 반환해야 한다는 것입니다.
 *
 * 이 예제에서 우리는 `switch` 구문과 문자열을 썼지만,
 * 여러분의 프로젝트에 맞게
 * (함수 맵 같은) 다른 컨벤션을 따르셔도 좋습니다.
 */
function counter(state = 0, action) {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1
    case 'DECREMENT':
      return state - 1
    default:
      return state
  }
}

// 앱의 상태를 보관하는 Redux 저장소를 만듭니다.
// API로는 { subscribe, dispatch, getState }가 있습니다.
let store = createStore(counter)

// subscribe()를 이용해 상태 변화에 따라 UI가 변경되게 할 수 있습니다.
// 보통은 subscribe()를 직접 사용하기보다는 뷰 바인딩 라이브러리(예를 들어 React Redux)를 사용합니다.
// 하지만 현재 상태를 localStorage에 영속적으로 저장할 때도 편리합니다.

store.subscribe(() => console.log(store.getState())))

// 내부 상태를 변경하는 유일한 방법은 액션을 보내는 것뿐입니다.
// 액션은 직렬화할수도, 로깅할수도, 저장할수도 있으며 나중에 재실행할수도 있습니다.
store.dispatch({ type: 'INCREMENT' })
// 1
store.dispatch({ type: 'INCREMENT' })
// 2
store.dispatch({ type: 'DECREMENT' })
// 1

mobx

  • MobX는 상태 관리를 간단하게 만들기 위한 기능적 반응 프로그래밍을 적용하는 상태관리 라이브러리이다.
  • 사용이 편리하고 구조가 자유롭다.

ex)

import React from "react"
import ReactDOM from "react-dom"
import { makeAutoObservable } from "mobx"
import { observer } from "mobx-react"

// 애플리케이션 상태를 모델링합니다.
class Timer {
    secondsPassed = 0

    constructor() {
        makeAutoObservable(this)
    }

    increase() {
        this.secondsPassed += 1
    }

    reset() {
        this.secondsPassed = 0
    }
}

const myTimer = new Timer()

// observable state를 사용하는 사용자 인터페이스를 구축합니다.
const TimerView = observer(({ timer }) => (
    <button onClick={() => timer.reset()}>Seconds passed: {timer.secondsPassed}</button>
))

ReactDOM.render(<TimerView timer={myTimer} />, document.body)

// 매초마다 Seconds passed: X를 업데이트 합니다.
setInterval(() => {
    myTimer.increase()
}, 1000)

swr

  • "SWR"이라는 이름은 HTTP RFC 5861에 의해 알려진 HTTP 캐시 무효 전략인 stale-while-revalidate에서 유래되었다.
  • SWR은 먼저 캐시(스태일)로부터 데이터를 반환한 후, fetch 요청(재검증)을 하고, 최종적으로 최신화된 데이터를 가져오는 전략이다.

ex)

import useSWR from 'swr'

function Profile() {
  const { data, error } = useSWR('/api/user', fetcher)

  if (error) return <div>failed to load</div>
  if (!data) return <div>loading...</div>
  return <div>hello {data.name}!</div>
}
  • 이 예시에서, useSWR hook은 key 문자열과 fetcher 함수를 받는다.
  • key는 데이터의 고유한 식별자이며(일반적으로 API URL) fetcher로 전달될 것이다.
  • fetcher는 데이터를 반환하는 어떠한 비동기 함수도 될 수 있다.
  • 네이티브 fetch 또는 Axios와 같은 도구를 사용할 수 있다.
  • hook은 두 개의 값을 반환한다: 요청의 상태에 기반한 data와 error.
profile
안녕하세요. 홍성표입니다.

0개의 댓글