redux, recoil 내용 정리

redux 와 recoil 은 무엇이 다른가

  • 최근에 상태관리라이브러리들이 많고, 그 개념들도 다르다. 그래서 정리를 하고자 작성
notion imagenotion image
  • flux 아키텍쳐의 데이터 흐름은 단방향이다.
  • Action 은 Action 을 생성 하여(type, payload) 이를 Dispatcher 에게 전달
  • Dispatch 는 모든 Action 을 전달받아 Store 에 전달을 해준다
  • Store 는 State 를 가지고 있고 State 를 변경해준다
  • Store 에서 State 변경 시, change 이벤트가 발생하면서 View 에게 State 가 변경되었다는걸 알려준다.(이때 View 에서 사용하는 State 는 업데이트가 일어난다 -> Rerender)
notion imagenotion image
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> ) }
// 상태 가공 or 상태 계산 const greet = useSelector(state => { return `${state.testReducer.name} Hello! (`${new Date().toISOString()}` )`; });
  • action 이 발생하여 store 가 업데이트 되면, 실제 name 값이 변경되지 않았어도 위 연산을 계속해서 처리함(배열이나 객체같은거 처리할수록 비용이 커짐) -> new Date 찍히는값이 계속해서 바뀔거다. 이는 해당 testReducer 가 업데이트가 일어나지 않아도 마찬가지..(다른 상태를 쓰고있다면 컴포넌트가 렌더링이 일어나고 컴포넌트가 렌더링될때 useSelector() 를 호출)
  • recoil 은 다른 개념을 제시함. Atom 이라는 상태 단위로 상태를 관리하며 컴포넌트는 이 Atom 을 구독하기만 하면 됨.
  • 저장소 개념보다는 작은 상태 단위(Atom)로 관리
  • recoil 은 redux 와 비교했을때 학습곡선 비용이 적으며 동시모드를 지원
  • 상태 변경으로 인한 불필요한 렌더링이 발생하지 않음(상태를 구독한 컴포넌트만 리랜더링 발생)
  • selector 를 통해 캐싱(기본적으로 값을 캐싱함)