redux 및 recoil 은 react 를 위한 상태관리(state management) 라이브러리
redux 는 Flux 아키텍쳐 기반
recoil 은 Atomic 모델 기반(Atom 이라는 작은 상태 단위로 관리하고 Atom 을 결합하여 데이터를 가공)
redux 는 중앙집중식으로 상태관리가 이루어진다. 실제로 전체 모델은 그렇게 복잡한편은 아니다.
// action types
export const UPDATE_NAME = `UPDATE/NAME`;
// action creator function
export const updateNameAction = name => ({type: UPDATE_NAME, payload: {name}});
// state
const initialState = {
name: '',
};
// reducer
const reducer = (state = initialState, action) => {
switch (action.type) {
case UPDATE_NAME :
return {
...state,
name: action.payload.name,
}
default :
return state
}
};
export default reducer
// store.js
import {combineReducers, createStore} from 'redux';
import testReducer from './modules/test/index';
const rootReducer = combineReducers({
testReducer
});
const store = createStore(rootReducer);
export default store
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
// redux
import store from './store/index';
import {Provider} from 'react-redux'
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<App/>
</Provider>
</React.StrictMode>,
document.getElementById('root')
);
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
// component
import React, {useEffect} from "react";
import {useSelector, useDispatch} from "react-redux";
import {
updateNameAction,
} from "../../store/modules/test";
export default function TestComponent() {
const dispatch = useDispatch();
const nameState = useSelector(state => state.testReducer.name);
const dispatchUpdateName = (name = 'basic') => {
dispatch(updateNameAction(name)); // action
};
useEffect(() => {
dispatchUpdateName();
}, []);
return (
<div>
<p>{nameState}</p>
</div>
)
}
redux 를 사용하기 위해서는 전체앱에 감싸야한다.
사용할 state 는 하나씩 해야한다. 만약 객체를 하는경우에는 성능이슈가 발생(매번 새로운 객체를 생성하기 때문)
useSelector() 훅같은 경우 두번째 인자로 react-redux 패키지에서 제공하는 shallowEqual 함수 전달이 가능하며 이전값과 다음값을 비교하는데 얕은 비교를 함
useSelector(selector: Function, equalityFn?: Function)
equalityFn?: (prev: any, next: any) => boolean
false 인 경우 rerender true 인 경우 rerender 하지 않음
이러한 비교연산은 BF(Brute Force) 방식으로 진행하므로 객체 키값들이 많으면 성능적으로 좋지 않고 하나하나 직접 작성하는거도 번거로움
파생된 상태(상태 계산)는 reselect 패키지에 의존해야 합니다.
// 상태 가공 or 상태 계산
const greet = useSelector(state => {
return `${state.testReducer.name} Hello! (`${new Date().toISOString()}`
)`;
});
아톰(atom) : 데이터 조각 or 상태 조각
셀렉터(selector):
1. 아톰에서 파생된 데이터 조각
2. 데이터를 반환하는 순수 함수
recoil 은 redux 와 비교했을때 적은 학습곡선을 가지고 있고, 코드량도 recoil 이 훨씬 적다
recoil 은 devTools 등 아직 부족한 부분이 많다(현재 버전은 0.3.1)
recoil 은 성능이점을 얻을 수 있으나, 대규모 프로젝트에 적용하기에는 좋은 사례라던가 레퍼런스들이 부족