next icon indicating copy to clipboard operation
next copied to clipboard

[Select]Select 或者 Radio 这种接受 dataSource 的组件,能否对传入的 value 做一个自动校验

Open AlphaCodeZero opened this issue 3 years ago • 2 comments

Component

Select

Feature Description

Select 或者 Radio 这种接受 dataSource 的组件,能否对传入的 value 做一个自动校验,比如传入的 value 不在 dataSource 数组中,或者在 dataSource 数组中但是是 disabled,这时候组件通过 onChange 自动将 value 修改成默认值或者 dataSource 第一个可选项 如果有这个功能的话,表单联动的时候会方便很多,具体场景:有 A, B 两个 Select,用户先选了 A,再选了 B,此时用户更改了 A,B 的 dataSource 发生了改变,之前选的 value 已经不在 dataSource 中了,这时候希望 B 能做自动修正。现在我能想到的方法是在 A 的 onChange 中手动修改 B 的值,但这种做法有点繁琐,特别是当表单联动的时候很复杂时 我个人感觉这个问题还是有些通用性的,因为向 Select, Radio 中传入一个不属于 dataSource 的值(或者 disabled 的值),本身可以看作是一种异常状态,而异常状态需要支持传入处理方法,或者有默认的处理方法

AlphaCodeZero avatar Jul 11 '22 04:07 AlphaCodeZero

你这个需求有些像 watch 或者类似的功能,你举的这个例子,其实 field 有提供一个全局监听 onChange 的方法,可以做联动。不过这个其实不太符合 react 的理念,我建议可以用 useEffect 去做联动,这样联动的逻辑也不用写在一起,每个联动的逻辑都可以对应着一个 useEffect,这个联动的 setValue 的逻辑是非常业务的,而且这个联动的决策需要考虑的因素可能在组件里面没法完全感知到,所以我建议在业务层去做这个联动。 对于你的例子,可能是这样的:


useEffect(() => {
  if (valueB 在 dataSource 中不存在) {
      setValueB(dataSource[0])
  }

// dataSorce 可能是因为 valueA 改变,也可能是其他原因
}, [valueB, dataSource])

lakerswgq avatar Jul 11 '22 06:07 lakerswgq

@lakerswgq 感谢回复,你说的这个方案确实是可行的,目前我是可以通过这么一层高阶组件的方式来实现我说的功能。 但我还是觉得这个问题是有通用性的,应该内置到 fusion 组件里面,因为我确实想不到向 Select 中传入一个不在 dataSource 中的值,有什么应用场景。其实不管是表单联动导致传入不可用的值,还是服务端返回的值不在前端的预料内,都可以认为是一种异常状态,那应该提供一个给业务方处理异常状态的接口,类似于

const someValueFromServer = 'a';
const OPTIONS = ['b', 'c'];

return (
  <Select
    value={someValueFromServer}
    dataSource={OPTIONS}
    onNotFound={() => OPTIONS[0]}
    onChange={(v) => console.log(v) /* 会打印出 'b' */}
  />
);

当然我觉得这个接口叫 onNotFound 确实局限了点,核心还是希望提供一个给业务方定义异常状态,以及处理异常状态的方式

AlphaCodeZero avatar Jul 12 '22 03:07 AlphaCodeZero

value 不在 dataSource 中是有场景的,select 的 tag模式是可以这么传递的,另外在一些业务场景比如:

  1. 展开时或搜索时才加载 dataSource 的懒加载场景
  2. 回显表单,从远程获取 dataSource 因权限等问题未返回当前选中的值对应的项时 从这些角度看这并非一个通用场景,而且在 didMount 或 update 时机自动触发 onChange 不符合 api 和 交互设计。

故而在业务使用侧实现才是上策。你建议的 onNotFound 在业务侧实现起来也十分简单:

const existsValue = OPTIONS.some(item => item === someValueFromServer) ? value : OPTIONS[0];
return <Select value={existsValue}/>;

YSMJ1994 avatar Jan 30 '24 10:01 YSMJ1994

Stale

YSMJ1994 avatar Feb 22 '24 11:02 YSMJ1994