React+valtio響應(yīng)式狀態(tài)管理
Valtio 是一個很輕量級的響應(yīng)式狀態(tài)管理庫。valtio 讓數(shù)據(jù)管理在 React 和原生 JS (Vanilla
) 中變得更加簡單的一個庫,它類似于 Vue 的數(shù)據(jù)驅(qū)動視圖的理念,使用外部狀態(tài)代理去驅(qū)動 React 視圖來更新。
一、狀態(tài)管理庫
dispatch
流派(單向數(shù)據(jù)流-中心化管理):redux
、zustand
、dva
等- 響應(yīng)式流派(中心化管理):
mobx
、valtio
等 - 原子狀態(tài)流派(原子組件化管理):
recoil
、jotai
等
值得一提的是:Jotai
、Zustand
、Valtio
這三個開源狀態(tài)管理庫都是出自一人之手。
zustand 德語 “狀態(tài)”,jotai 日語 “狀態(tài)”、valtio 芬蘭語 “狀態(tài)”。
作者叫做 Daishi Kato,他是日本東京人,是個全職開源作者。
二、Jotai、Zustand、Valtio 使用對比
- Zustand
import { create } from "zustand"; const useStore = create((set) => ({ count: 0, inc: () => set((state) => ({ count: state.count + 1 })), })); export default function Counter() { const count = useStore((state) => state.count); const inc = useStore((state) => state.inc); return ( <div> {count} <button onClick={inc}>+1</button> </div> ); }
- Jotai:每個狀態(tài)都是原子化,用法和原生的 useState 有點像
import { atom, useAtom } from "jotai"; const countAtom = atom(0); function Counter() { const [count, setCount] = useAtom(countAtom); return ( <div> {count} <button onClick={() => setCount((v) => v + 1)}>+1</button> </div> ); }
- Valtio:和 Vue 的響應(yīng)式類似,當(dāng)數(shù)據(jù)發(fā)生變化的時候就驅(qū)動視圖更新
const state = proxy({ dur: 10, count: 1102 }); const incDur = () => {++state.dur}; const decDur = () => {--state.dur}; const incCount = () => { ++state.count; setTimeout(incCount, 100 * state.dur); }; incCount(); export default function Main() { const snap = useSnapshot(state) return ( <div> <h3>{snap.dur}</h3> <button disabled={snap.dur <= 1} onClick={decDur}> - </button> <button disabled={snap.dur >= 10} onClick={incDur}> + </button> </div> ); }
三、Valtio 狀態(tài)管理最佳實踐
- 創(chuàng)建一個
store.js
文件
import { proxy } from 'valtio' import { useProxy } from 'valtio/utils' import { cloneDeep } from 'lodash-es' export const defaultData = { activeIndex: 0, rangeData: [5, 20], baseSelected: [], step: { 1: true, 2: false, 3: false, 4: false, 5: false, 6: false, }, } const state = cloneDeep(defaultData) const store = proxy(state) export const useStore = () => { return useProxy(store) } export function resetData() { Object.entries(defaultData).forEach( ([key, value]) => { store[key] = cloneDeep(value) } ) }
- 在組件中使用
import { useStore, resetData } from '@/store/store' const tabs = [ { value: '1', label: '基礎(chǔ)設(shè)置', }, { value: '2', label: '高級設(shè)置', }, { value: '3', label: '其他設(shè)置', } ] const list = [ { value: '1', label: '標(biāo)簽' }, { value: '2', label: '分類' }, { value: '3', label: '作者' }, ] export default function Main() { const store = useStore() useEffect(() => { return () => { // 在組件卸載的時候重置數(shù)據(jù) resetData() } }, []); function onSelect(id) { if (store.baseSelected.includes(id)) { store.baseSelected = store.baseSelected.filter( (item) => item !== id ) } else { if (store.baseSelected.length >= 5) return store.baseSelected.push(id) } } return ( <div> { tabs.map(({ value, label }, index) => ( <div key={value} onClick={() => { store.activeIndex = index }} > {label} </div> )) } <hr/> { list.map(({ value, label }) => ( <div key={value} onClick={() => { onSelect(value) }} > {label} </div> )) } </div> ); }
useProxy
其實就是對取 useSnapshot()
或 store
數(shù)據(jù)的封裝,這個 hook 也很簡單,就是判斷是渲染期間(渲染體內(nèi))就返回 useSnapshot()
的快照數(shù)據(jù),非渲染期間(非渲染體內(nèi))就返回原始的 store 數(shù)據(jù),和我們自己手寫的是差不多的,只不過這個 hook 幫我們把這個過程封裝了起來。
到此這篇關(guān)于React+valtio響應(yīng)式狀態(tài)管理的文章就介紹到這了,更多相關(guān)React valtio響應(yīng)式狀態(tài)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
nodejs和react實現(xiàn)即時通訊簡易聊天室功能
這篇文章主要介紹了nodejs和react實現(xiàn)即時通訊簡易聊天室功能,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-08-08JS中使用react-tooltip插件實現(xiàn)鼠標(biāo)懸浮顯示框
前段時間遇到的一個需求,要求鼠標(biāo)懸停顯示使用描述, 用到了react-tooltip插件,今天寫一個總結(jié),感興趣的朋友跟隨小編一起看看吧2019-05-05關(guān)于antd tree和父子組件之間的傳值問題(react 總結(jié))
這篇文章主要介紹了關(guān)于antd tree 和父子組件之間的傳值問題,是小編給大家總結(jié)的一些react知識點,本文通過一個項目需求實例代碼詳解給大家介紹的非常詳細,需要的朋友可以參考下2021-06-06利用React Router4實現(xiàn)的服務(wù)端直出渲染(SSR)
這篇文章主要介紹了利用React Router4實現(xiàn)的服務(wù)端直出渲染(SSR),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-01-01