React 에는 전역상태를 관리하는 여러가지 라이브러리가 존재한다.
하나씩 알아보도록 하자.
사용이 편리하지만 속도가 느리고 렌더 성능상의 이슈가 있다.
Redux의 세가지 원칙
구조가 복잡하지만 자주 업데이트 되는 앱에서 효율적인 사용이 가능하다.
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
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)
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>
}