You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
import{atom,selector}from"recoil";import{mockRegionData}from"./mock";exportconstregionsState=selector({key: "regionsState",get: ({ get })=>{returnPromise.resolve<IRegion[]>(mockRegionData);},});
添加一个状态用于保存当前选中的地域:
appState.ts
exportconstregionState=atom({key: "regionState",default: selector({key: "regionState/Default",get: ({ get })=>{constregions=get(regionsState);returnregions[0];},}),});
Recoil 默认值及数据级联的使用
Recoil 中默认值及数据间的依赖
通过 Atom 可方便地设置数据的默认值,
而 Selector 可方便地设置数据的级联依赖关系,即,另一个数据可从现有数据进行派生。
结合这两个特点,在实现数据间存在联动的表单时,非常方便。
一个实际的例子
考察这样的场景,购买云资源时,会先选择地域,根据所选地域再选择该地域下的可用区。
这里就存在设置默认值的问题,未选择时自动选中默认地域及对应地域下的默认可用区,也涉及数据间的级联依赖,可选的可用区要根据地域而变化。
呈现的效果如下:

地域及可用区的选择
实现地域及可用区的选择
下面就通过 Recoil 来实现上述地域及可用区的选择逻辑。
创建示例项目
添加并使用 Recoil
安装依赖:
使用 Recoil, 首先将应用包裹在
RecoilRoot
中:index.tsx
添加
appState.ts
文件存放 Recoil 状态数据,目前先定义好地域和可用区的类型,appState.ts
添加假数据
根据上面定义的类型,添加假数据:
mock.ts
添加状态数据
添加地域及可用区状态数据,先看地域数据,该数据用来生成地域的下拉框。真实情况下,该数据来自异步请求,这里通过 Promise 模拟异步数据。
appState.ts
添加一个状态用于保存当前选中的地域:
appState.ts
这里通过使用 atom 并指定默认值为地域第一个数据,达到下拉框默认选中第一个的目的。
添加地域选择组件
添加地域选择组件,使用上面创建的地域数据。
RegionSelect.tsx
至此地域部分完成,可用区同理,只不过可用区的拉下数据依赖于当前选中的地域。
添加可用区状态数据及下拉组件
appState.tsx
可选择的可用区依赖于当前选中的地域,通过
const region = get(regionState);
实现获取到当前选中地域的目的。可用区的默认值也是拿到当前可选的所有地域,然后取第一个,
return get(zonesState)[0];
。ZoneSelect.tsx
展示当前地域及可用区
将前面两个下拉框展示出来,同时展示当前地域及可用区。
App.tsx
至此完成了整个程序的实现。
最终效果
来看看效果:
地域及可用区联动效果
带默认值的状态未自动更新的问题
上面的实现乍一看实现了功能,但进行可用区的选择之后问题便会暴露。

可用区未联动的问题
可以看到可用区更新后,再切换地域,虽然下拉框中可选的可用区更新了,但实际上当前可用区的值停留在了上一次选中的值,并没有与地域联动。如果不是把可用区展示出来,不容易发现这里的问题,具有一定迷惑性。
看看可用区下拉值
zones
的来源不难发现,因为可用区是从当前选中的地域数据
regionState
中获取的,当变更地域后,regionState
更新,导致zonesState
更新,所以下拉框能正确同步,没问题。再看看当前选中的可用区
zoneState
:它通过
atom
承载,同时指定了默认值,为zonesState
中第一个数据。当切换地域时,
zonesState
确实更新了,进而zoneState
的默认值也会重新获取,所以始终会默认选中第一个可用区。当我们手动进行了可用区选择时,在可用区下拉组件中,
onChange
事件的回调中通过setZone
更新了zoneState
,此时可用区zoneState
已经有一个人为设置的值,默认值就不起作用了,因此在切换地域后,zoneState
仍为这里onChange
设置的值。手动添加依赖
直接的修复方式可以在可用区组件中监听地域的变化,当地域变化后,设置一次可用区。
能达到目的,但通过打印出来的可用区值来看,当地域切换后,可用区的值更新并不及时,首先会打印出一个错误的值,待
useEffect
执行完毕后,才打印出正确的值,即,这种方式的修复,有滞后性。
通过 `useEffect` 方式来修正,可用区更新会滞后
useResetRecoilState
查阅 Recoil 文档,发现
useResetRecoilState
可用于重置状态到默认值。这里的思路可以是,在地域变化后,重置一下可用区,这样之前手动选择的值便失效,可用区恢复到默认状态。
这里
resetZone
和setRegion
的顺序不影响,都能达到目的。
通过 `useResetRecoilState` 重置状态到默认值
通过打印的值来看,一切正常,问题得以修正。
相关资源
useResetRecoilState
The text was updated successfully, but these errors were encountered: