Recoil 中預設值的正確處理

劉哇勇發表於2021-04-13

繼續使用 Recoil 預設值及資料級聯的使用 的地域可用區級聯的例子。

地域變更後可用區隨之聯動,兩個下拉框皆預設選中第一個可選項。

從 URL 獲取預設值

考慮這種情況,當 URL 中帶了 query 引數指定地域時,想要預設選中指定的地域。

首先安裝一個解析 query 的庫 query-string 方便獲取 query 並解析引數。

$ yarn add query-string

這樣在地域元件中,就需要處理 URL 中的引數,如果發現帶參,則更新地域資訊。

RegionSelect.tsx

import { parse } from "query-string";
import React, { useEffect } from "react";
import { useRecoilState, useRecoilValue } from "recoil";
import { regionsState, regionState } from "./appState";

export function RegionSelect() {
  const regions = useRecoilValue(regionsState);
  const [region, setRegion] = useRecoilState(regionState);
  const regionId = parse(window.location.search).region;

  useEffect(() => {
    if (regionId) {
      const urlRegion = regions.find((region) => region.id === regionId);
      if (urlRegion) {
        setRegion(urlRegion);
      }
    }
  }, [regionId, regions, setRegion]);

  return (

  );
}

同時將當前地域資訊列印出來,可以預見,上面因為在 useEffect 中處理的 URL 引數(元件中也只能在這裡面處理),必然會有滯後性。也就是說,會先列印 beijing,再列印 URL 中指定的 shanghai

Screen Recording 2021-03-05 at 8 34 49 PM mov

useEffect 中處理URL 具有滯後性

在 Recoil 中處理

值得注意的是,atom 的預設值可以來自任何地方,非同步資料或其他 atom 等,那當然也可以來自 URL。

按照這個思路將從 URL 獲取地域的邏輯挪到 atom 的預設值獲取邏輯中便解決了上述滯後的問題。

appState.ts

export const regionState = atom({
  key: "regionState",
  default: selector({
    key: "regionState/Default",
    get: ({ get }) => {
      const regions = get(regionsState);
+      const regionId = parse(window.location.search).region;
+      if (regionId) {
+        const urlRegion = regions.find((region) => region.id === regionId);
+        if (urlRegion) {
+          return urlRegion;
+        }
+      }
      return regions[0];
    },
  }),
});

Screen Recording 2021-03-05 at 8 44 25 PM mov

在 atom 中處理引數的獲取

The text was updated successfully, but these errors were encountered:

相關文章