Recoil 中默认值的正确处理
Recoil 中默认值的正确处理
继续使用 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
。

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];
},
}),
});

在 atom 中处理参数的获取