React中的狀態(tài)管理是開發(fā)人員需要解決的問題。 總有一些新庫給你選擇谬以,而選擇合適的庫可能是一項困難的工作
狀態(tài)管理一直是React中開發(fā)人員需要解決的問題盯串,如何有條理的組織數(shù)據(jù)戴陡,如何快速的在項目中集成,這些都是我們做項目時選擇技術的標準绰更。
Redux一直是我們react項目中不二的狀態(tài)管理插件,但是redux的配置以及各種插件的安裝一直是很多人員頭疼的一個問題,太麻煩了。但是隨著ReduxToolkit的出現(xiàn),確實解決了這個問題邑雅,直接安裝,就不再需要繼續(xù)安裝各類其他插件妈经,直接上手就能用淮野,簡單方便。但是很多時候吹泡,我們的項目可能根本不需要這么笨重的插件骤星,雖然redux很好,但是畢竟這么多年過去了爆哑,一代新人換舊人洞难。前端這個大坑中,總會出現(xiàn)新的技術揭朝、框架來埋葬那些老家伙队贱。
代理
Proxy對象用于創(chuàng)建一個對象的代理,從而實現(xiàn)基本操作的攔截和自定義(如屬性查找潭袱、賦值柱嫌、枚舉、函數(shù)調用等)屯换。
自ES6版本以來编丘,我們在JavaScript中有代理。 代理接收兩個參數(shù):
target - 要代理的原始對象
handler - 定義對象的操作
這是我們如何使用JavaScript創(chuàng)建代理的方式:
const handler = {
? get: function (obj, prop) {
? ? return prop in obj ? obj[prop] : 37;
? },
};
const p = new Proxy({}, handler);
p.a = 1;
p.b = undefined;
console.log(p.a, p.b); // 1, undefined
console.log('c' in p, p.c); // false, 37
Valtio
Valtio是一個用于對React和JavaScript應用程序簡單的代理狀態(tài)的庫彤悔。它使用了js中Proxy這個語法嘉抓,能讓我們可以非常方便的在react中集成狀態(tài)管理功能。
npminitvite@latest#創(chuàng)建react項目npmivaltio#進入項目晕窑,安裝依賴
我們需要做的是包裝我們的狀態(tài)對象抑片,然后我們可以在我們的應用程序中的任何地方進行改變:
import{proxy}from'valtio';typeIStore={count:number;list:Item[];};// 定義數(shù)據(jù),使用proxy進行包括修飾
conststore=proxy<IStore>({count:1,list:[],});/**
* 改變數(shù)據(jù)
* @param step
*/exportconstcountPlus=(step:number)=>{store.count+=step;};/**
* 新增數(shù)據(jù)到列表
* @param txt
*/exportconstaddToList=(txt:string)=>{store.list.push({id:Date.now(),txt,});};exportdefaultstore;
定義好的數(shù)據(jù)直接在組件中進行引入就能使用杨赤,useSnapshot可以獲取我們定義好的狀態(tài)數(shù)據(jù)蓝丙,使用之后在組件中就是一個響應式的效果,只要數(shù)據(jù)改變了組件就會直接進行更新
import{useSnapshot}from'valtio';importstore,{countPlus}from'../store';functionCounter(){const{count}=useSnapshot(store);return(<div><h1>計數(shù)器--{count}</h1><buttononClick={()=>{countPlus(2);}}>改變</button></div>);}exportdefaultCounter;
valtio簡單直接望拖,充分使用了proxy這個對象,簡單粗暴的實現(xiàn)react項目的狀態(tài)管理挫鸽。在一些小型項目中是一個不錯的選擇说敏。當然當然大家還是需要在項目中努力做好自己代碼結構的組織方便后去數(shù)據(jù)的維護。
├──index.html├──package-lock.json├──package.json├──public│└──vite.svg├──readme.md├──src│├──@types││└──app.d.ts│├──App.css│├──App.tsx│├──assets││└──react.svg│├──components││├──Counter.tsx││├──List│││├──index.tsx│││└──list-input.tsx││├──Movies.tsx││└──ShowCounter.tsx│├──index.css│├──main.tsx│├──store││├──features│││└──movie.ts││└──index.ts│└──vite-env.d.ts├──tsconfig.json├──tsconfig.node.json└──vite.config.ts
store丢郊,目錄存儲valtio的數(shù)據(jù)盔沫。index.ts做為入口医咨,可以引入其他的子節(jié)點數(shù)據(jù)
store/features,目錄可以根據(jù)功能做拆分處理架诞。每一個功能對應一個文件
比如此處我的movie.ts文件的內容如下
// store/features/movie.ts
import{proxy}from'valtio';// 進行分割
exportconstmovie=proxy({movies:[],});exportconstloadMovieData=async()=>{constres=awaitfetch('https://pcw-api.iqiyi.com/search/recommend/list?channel_id=2&data_type=1&mode=11&page_id=2&ret_num=48&session=ffad98ae609f650afe4b60e205948ac1&three_category_id=15;must').then((data)=>data.json());movie.movies=res.data.list;};
完成的store/index.ts文件如下
import{proxy}from'valtio';import{movie}from'./features/movie';/**
* 定義數(shù)據(jù)
*/conststore=proxy<IStore>({count:1,list:[],movie,// 引入拆分好的文件
});/**
* 改變數(shù)據(jù)
* @param step
*/exportconstcountPlus=(step:number)=>{store.count+=step;};/**
* 新增數(shù)據(jù)到列表
* @param txt
*/exportconstaddToList=(txt:string)=>{store.list.push({id:Date.now(),txt,});};exportdefaultstore;
而我組件中如果要獲取數(shù)據(jù)拟淮,可以直接拿來用
// components/Movie.tsx
import{useEffect}from'react';import{useSnapshot}from'valtio';importstorefrom'../store';import{loadMovieData}from'../store/features/movie';functionMovies(){const{movie}=useSnapshot(store);// useSnapshot取數(shù)據(jù)
// console.log(movie);
useEffect(()=>{loadMovieData();},[]);return(<divclassName='movies'><ul>{movie.movies.map((item:any)=>(<likey={item.albumId}>{item.name}</li>))}</ul></div>);}exportdefaultMovies;