onBlur比onChange更适合省市区三级联动,因用户常通过Tab或鼠标跳转导致onChange不触发,而onBlur能可靠捕获焦点离开动作以加载下级数据;需配合受控模式、正确useEffect依赖、空数组兜底及准确Form.Item name路径。

为什么 onBlur 比 onChange 更适合省市区三级联动
因为用户在 Select 中选择“省份”后,往往不会立刻点开“城市”下拉框——而是直接用键盘 Tab 跳转,或鼠标点击下一个字段。此时 onChange 不触发(值未变),但 onBlur 会稳稳捕获“离开当前字段”这一动作,正好作为加载下级数据的信号。
常见错误是监听 onChange 后发现城市列表迟迟不更新,尤其在快速切换或键盘操作时;而用 onBlur 后,只要焦点移出,就清空下级、发起请求、设 loading 状态,行为更可控。
- 省市区字段必须用受控模式:
value+onChange配合onBlur触发联动 - 省一级可只用
onChange,但市/区两级强烈建议加onBlur防止误触或跳过校验 - 注意防抖:对
onBlur不需防抖,但若配合搜索型Select,则输入时的onChange要加setTimeout或useDebounce
useEffect 依赖数组里漏掉 provinceId 就会卡死联动
当用 useEffect 加载城市列表时,如果只写 [cityList] 或空数组 [],那么 provinceId 变了,effect 也不会重跑——城市列表永远停留在上一个省的数据里,用户换省后城市选项不变,这是最常被忽略的硬伤。
正确写法必须把驱动下级加载的变量放进依赖:比如 useEffect(() => { loadCities(provinceId) }, [provinceId])。如果用了 useCallback 包裹 loadCities,还要确保它的依赖也完整,否则闭包里还是旧 provinceId。
Orderly React SDK 钩子使用参考指南,包括 useOrderEntry、usePositionStream、useOrderbookStream、useCollateral 等。
- 检查控制台是否有 “React Hook useEffect has a missing dependency” 警告,它不是建议,是 bug 提示
- 如果
provinceId来自表单字段,确认它不是字符串"1"和数字1混用——后端返回的 id 类型要和前端传参类型一致,否则useEffect依赖比对失败 - 加载中状态(
loading)不要放在 effect 里 setState,否则可能触发无限循环;改用useState单独管理,或用useReducer统一处理
区县列表为空时,Select 的 options 不能传 undefined 或 null
很多同学在接口返回空数组或还没请求时,直接把 districtOptions 设为 undefined,结果 Select 报错:Cannot read property 'map' of undefined,或者下拉框显示空白但可点击,点开后无选项、无 loading、无提示。
React 组件要求 options 必须是数组,哪怕空也要是 []。哪怕后端没返回数据,前端也得兜底:
const districtOptions = Array.isArray(districts) ? districts.map(item => ({ value: item.code, label: item.name })) : [];
- 后端返回格式不统一(有时是
{ data: [...] },有时是[],有时是null)时,务必在请求响应后做归一化处理 - 别在 render 里写
{districts && districts.map(...)},这会导致options是false或undefined,Select内部无法处理 - 空状态可以加 placeholder 提示,比如“请先选择城市”,但前提是
options是合法空数组,不是undefined
Form.Item 的 name 嵌套路径写错导致 setFieldsValue 失效
三级联动字段若放在嵌套对象里,比如表单值结构是 { address: { province: '1', city: '101', district: '10101' } },那 Form.Item 的 name 必须写成 ['address', 'province'],而不是 'address.province' 或 'province'。写错后,form.setFieldsValue({ address: { city: '' } }) 根本不会清空城市字段,联动就断了。
- Ant Design 的
name是数组形式的路径,不是字符串路径;setFieldsValue也是按数组路径匹配更新 - 联动中清空下级字段时,别只调
form.setFieldValue('city', ''),得用完整路径:form.setFieldValue(['address', 'city'], '') - 调试时可用
form.getFieldsValue()打印当前值,确认结构是否和name匹配;不匹配就说明路径写错了

















