# jotai ## 前言 其實很多state management有一個概念很重要,資料處理與畫面渲染是兩件事情,以redux來説store只是負責資料的CRUD實際上他無法觸發react的render ### redux sub 介紹 ```typescript import { addTodo, toggleTodo, setVisibilityFilter, VisibilityFilters } from './actions' // 記錄初始 state console.log(store.getState()) // 每次 state 變更,就記錄它 // 記得 subscribe() 會回傳一個用來撤銷 listener 的 function let unsubscribe = store.subscribe(() => console.log(store.getState()) ) // Dispatch 一些 action store.dispatch(addTodo('Learn about actions')) store.dispatch(addTodo('Learn about reducers')) store.dispatch(addTodo('Learn about store')) store.dispatch(toggleTodo(0)) store.dispatch(toggleTodo(1)) store.dispatch(setVisibilityFilter(VisibilityFilters.SHOW_COMPLETED)) // 停止監聽 state 的更新 unsubscribe() ``` ![](https://i.imgur.com/tzUO0UB.png) ### jotai sub sub functions ```typescript const subscribeAtom = (atom, listener) => { const mounted = addAtom(atom); flushPending(); const listeners = mounted.l; listeners.add(listener); if ((import.meta.env && import.meta.env.MODE) !== "production") { storeListeners.forEach((l) => l("sub")); } return () => { listeners.delete(listener); delAtom(atom); if ((import.meta.env && import.meta.env.MODE) !== "production") { storeListeners.forEach((l) => l("unsub")); } }; }; ``` ### useAtom ```typescript export function useAtomValue<Value>(atom: Atom<Value>, options?: Options) { const store = useStore(options) const [[valueFromReducer, storeFromReducer, atomFromReducer], rerender] = useReducer< ReducerWithoutAction<readonly [Value, Store, typeof atom]>, undefined >( (prev) => { const nextValue = store.get(atom) if ( Object.is(prev[0], nextValue) && prev[1] === store && prev[2] === atom ) { return prev } return [nextValue, store, atom] }, undefined, () => [store.get(atom), store, atom] ) let value = valueFromReducer if (storeFromReducer !== store || atomFromReducer !== atom) { rerender() value = store.get(atom) } const delay = options?.delay useEffect(() => { const unsub = store.sub(atom, () => { if (typeof delay === 'number') { // delay rerendering to wait a promise possibly to resolve setTimeout(rerender, delay) return } rerender() }) rerender() return unsub }, [store, atom, delay]) useDebugValue(value) return isPromise(value) ? use(value) : (value as Awaited<Value>) } ``` 重點這邊觸發react render的 ```typescript useEffect(() => { const unsub = store.sub(atom, () => { if (typeof delay === 'number') { // delay rerendering to wait a promise possibly to resolve setTimeout(rerender, delay) return } rerender() }) rerender() return unsub }, [store, atom, delay]) ``` #### jotai回饋 ```typescript lucy: sub = useEffect的dependence 監聽 他不會影響渲染 要渲染要在裡面進行setState之類的行為 要即時render用useAtom ```