Recoil 中預設值及資料間的依賴通過 Atom 可方便地設定資料的預設值, const fontSizeState = atom({
key: 'fontSizeState',
default: 14,
});
而 Selector 可方便地設定資料的級聯依賴關係,即,另一個資料可從現有資料進行派生。 const fontSizeLabelState = selector({
key: 'fontSizeLabelState',
get: ({get}) => {
const fontSize = get(fontSizeState);
const unit = 'px';
return `${fontSize}${unit}`;
},
});
結合這兩個特點,在實現資料間存在聯動的表單時,非常方便。 一個實際的例子考察這樣的場景,購買雲資源時,會先選擇地域,根據所選地域再選擇該地域下的可用區。 這裡就存在設定預設值的問題,未選擇時自動選中預設地域及對應地域下的預設可用區,也涉及資料間的級聯依賴,可選的可用區要根據地域而變化。 呈現的效果如下: 地域及可用區的選擇 實現地域及可用區的選擇下面就通過 Recoil 來實現上述地域及可用區的選擇邏輯。 建立示例專案$ yarn create react-app recoil-nest-select --template typescript
新增並使用 Recoil安裝依賴: $ yarn add recoil
使用 Recoil, 首先將應用包裹在 index.tsx import { RecoilRoot } from "recoil";
ReactDOM.render(
<React.StrictMode>
<RecoilRoot>
<Suspense fallback="loading...">
<App />
</Suspense>
</RecoilRoot>
</React.StrictMode>,
document.getElementById("root")
);
新增 appState.ts interface IZone {
id: string;
name: string;
}
interface IRegion {
id: string;
name: string;
zones: IZone[];
}
新增假資料根據上面定義的型別,新增假資料: mock.ts export const mockRegionData = [
{
id: "beijing",
name: "北京",
zones: [
{
id: "beijing-zone-1",
name: "北京一區",
},
{
id: "beijing-zone-2",
name: "北京二區",
},
{
id: "beijing-zone-3",
name: "北京三區",
},
],
},
{
id: "shanghai",
name: "上海",
zones: [
{
id: "shanghai-zone-1",
name: "上海一區",
},
{
id: "shanghai-zone-2",
name: "上海二區",
},
{
id: "shanghai-zone-3",
name: "上海三區",
},
],
},
{
id: "guangzhou",
name: "廣州",
zones: [
{
id: "guangzhou-zone-1",
name: "廣州一區",
},
{
id: "guangzhou-zone-2",
name: "廣州二區",
},
],
},
];
新增狀態資料新增地域及可用區狀態資料,先看地域資料,該資料用來生成地域的下拉框。真實情況下,該資料來自非同步請求,這裡通過 Promise 模擬非同步資料。 appState.ts import { atom, selector } from "recoil";
import { mockRegionData } from "./mock";
export const regionsState = selector({
key: "regionsState",
get: ({ get }) => {
return Promise.resolve<IRegion[]>(mockRegionData);
},
});
新增一個狀態用於儲存當前選中的地域: appState.ts export const regionState = atom({
key: "regionState",
default: selector({
key: "regionState/Default",
get: ({ get }) => {
const regions = get(regionsState);
return regions[0];
},
}),
});
這裡通過使用 atom 並指定預設值為地域第一個資料,達到下拉框預設選中第一個的目的。 新增地域選擇元件新增地域選擇元件,使用上面建立的地域資料。 RegionSelect.tsx import React from "react";
import { useRecoilState, useRecoilValue } from "recoil";
import { regionsState, regionState } from "./appState";
export function RegionSelect() {
const regions = useRecoilValue(regionsState);
const [region, setRegion] = useRecoilState(regionState);
return (
<label htmlFor="regionId">
地域:
<select
name="regionId"
id="regionId"
value={region.id}
onChange={(event) => {
const regionId = event.target.value;
const region = regions.find((region) => region.id === regionId);
setRegion(region!);
}}
>
{regions.map((region) => (
<option key={region.id} value={region.id}>
{region.name}
</option>
))}
</select>
</label>
);
}
至此地域部分完成,可用區同理,只不過可用區的拉下資料依賴於當前選中的地域。 新增可用區狀態資料及下拉元件appState.tsx export const zonesState = selector({
key: "zonesState",
get: ({ get }) => {
const region = get(regionState);
return region.zones;
},
});
export const zoneState = atom({
key: "zoneState",
default: selector({
key: "zoneState/default",
get: ({ get }) => {
return get(zonesState)[0];
},
}),
});
可選擇的可用區依賴於當前選中的地域,通過 可用區的預設值也是拿到當前可選的所有地域,然後取第一個, ZoneSelect.tsx import React from "react";
import { useRecoilState, useRecoilValue } from "recoil";
import { zonesState, zoneState } from "./appState";
export function ZoneSelect() {
const zones = useRecoilValue(zonesState);
const [zone, setZone] = useRecoilState(zoneState);
return (
<label htmlFor="zoneId">
可用區:
<select
name="zoneId"
id="zoneId"
value={zone.id}
onChange={(event) => {
const zoneId = event.target.value;
const zone = zones.find((zone) => zone.id === zoneId);
setZone(zone!);
}}
>
{zones.map((zone) => (
<option key={zone.id} value={zone.id}>
{zone.name}
</option>
))}
</select>
</label>
);
}
展示當前地域及可用區將前面兩個下拉框展示出來,同時展示當前地域及可用區。 App.tsx import React from "react";
import { useRecoilValue } from "recoil";
import "./App.css";
import { regionState, zoneState } from "./appState";
import { RegionSelect } from "./RegionSelect";
import { ZoneSelect } from "./ZoneSelect";
function App() {
const region = useRecoilValue(regionState);
const zone = useRecoilValue(zoneState);
return (
<div className="App">
<p>region:{region.name}</p>
<p>zone:{zone.name}</p>
<RegionSelect />
<ZoneSelect />
</div>
);
}
export default App;
至此完成了整個程式的實現。 最終效果來看看效果: 地域及可用區聯動效果 帶預設值的狀態未自動更新的問題上面的實現乍一看實現了功能,但進行可用區的選擇之後問題便會暴露。 可用區未聯動的問題 可以看到可用區更新後,再切換地域,雖然下拉框中可選的可用區更新了,但實際上當前可用區的值停留在了上一次選中的值,並沒有與地域聯動。如果不是把可用區展示出來,不容易發現這裡的問題,具有一定迷惑性。 看看可用區下拉值 export const zonesState = selector({
key: "zonesState",
get: ({ get }) => {
const region = get(regionState);
return region.zones;
},
});
因為可用區是從當前選中的地域資料 再看看當前選中的可用區 export const zoneState = atom({
key: "zoneState",
default: selector({
key: "zoneState/default",
get: ({ get }) => {
return get(zonesState)[0];
},
}),
});
它通過 當切換地域時, 當我們手動進行了可用區選擇時,在可用區下拉元件中, <select
name="zoneId"
id="zoneId"
value={zone.id}
+ onChange={(event) => {
+ const zoneId = event.target.value;
+ const zone = zones.find((zone) => zone.id === zoneId);
+ setZone(zone!);
}}
>
{zones.map((zone) => (
<option key={zone.id} value={zone.id}>
{zone.name}
</option>
))}
</select>
手動新增依賴直接的修復方式可以在可用區元件中監聽地域的變化,當地域變化後,設定一次可用區。 export function ZoneSelect() {
+ const region = useRecoilValue(regionState);
const zones = useRecoilValue(zonesState);
const [zone, setZone] = useRecoilState(zoneState);
+ console.log("zone:", zone.id);
+ useEffect(() => {
+ setZone(zones[0]);
+ }, [region]);
return (
<label htmlFor="zoneId">
…
</label>
);
}
能達到目的,但通過列印出來的可用區值來看,當地域切換後,可用區的值更新並不及時,首先會列印出一個錯誤的值,待 通過 `useEffect` 方式來修正,可用區更新會滯後
|
The text was updated successfully, but these errors were encountered: |
Recoil 預設值及資料級聯的使用
相關文章
- Recoil 中多級資料聯動及資料重置的合理做法
- Recoil 中預設值的正確處理
- Vantui---picker三級聯動設定預設值UI
- Recoil 的使用
- 資料庫事務隔離級別的深坑:預設值應修改為SERIALIZABLE資料庫
- jeefast框架 修改的下拉框三級聯動預設顯示後臺資料AST框架
- Navicat for MySQL 15使用教程:何時使用預設值以及如何選用恰當的預設值MySql
- 使用cglib實現資料庫框架的級聯查詢CGLib資料庫框架
- ${VAR:=預設值}和${VAR:-預設值} 區別
- 預設值的作用域
- 生成 URL 的 預設值
- HTML 元素的預設值HTML
- MySQL 5 不允許TEXT資料型別的列有預設值的問題!MySql資料型別
- 若依框架——>三級聯動 新增,預設修改框架
- 細聊Concent & Recoil , 探索react資料流的新開發模式React模式
- SQL Server資料庫建立新使用者及關聯資料庫的方法教程SQLServer資料庫
- 基本資料型別以及String未初始化賦予的預設值資料型別
- HTML常用元素的預設值HTML
- MySQL預設資料庫的作用MySql資料庫
- Navicat 連線遠端資料庫及 SSH 預設埠號的修改資料庫
- 預設值+TS型別約束提高資料處理成功率型別
- [轉]MySQL的datetime設定當前時間為預設值及 triger 一例MySql
- 024、Vue3+TypeScript基礎,使用withDefaults在父傳子沒資料時給出預設值VueTypeScript
- Mysql資料庫值的新增、修改、刪除及清空MySql資料庫
- ES6小技巧 - 使用解構賦值設定函式引數預設值賦值函式
- ABP預設模板修改預設資料庫型別並初始化資料庫資料資料庫型別
- HTTP請求預設值HTTP
- Laravel 生成 url,預設值Laravel
- mysql datetime增加預設值MySql
- SAP UI5 Theme Library 的解析邏輯和 SAP UI5 配置後設資料的預設值UI
- mysql資料庫安裝及預設儲存路徑修改方法MySql資料庫
- sql設定欄位預設值SQL
- 在Xamarin.iOS專案中使用預設資料庫iOS資料庫
- mybatis-plus 透過 updateById 更新部分欄位資料時出現所有資料被更新(被設為預設值)MyBatis
- Vue-使用ElementUI級聯選擇器懶載入省市縣資料VueUI
- Postgresql 的預設隔離級別SQL
- Golang技巧之預設值設定的高階玩法Golang
- 符合 iview 資料規則的省市區三級聯動View