Formik多语言表单实现国家-城市-电话区号下拉联动
Formik多语言三级联动下拉实现方案
前置数据结构规范
所有配置数据统一维护在data.js中,提前打通三个字段的关联映射关系,从结构上保障联动逻辑可落地:
- 多语言国家列表:每一项需包含唯一
countryId、对应各语言版本的国家名称文本 - 城市映射表:以
countryId为键,值为对应国家下的城市数组,每个城市项包含唯一cityId、对应各语言版本的城市名称文本 - 电话区号映射表:以
countryId为键,值为对应国家的标准电话区号字符串
// data.js 核心结构示例 export const multiLangCountryList = [ { id: 'CN', name: { zh: '中国', en: 'China' } }, { id: 'US', name: { zh: '美国', en: 'United States' } } ] export const cityMapByCountry = { CN: [ { id: 'BJ', name: { zh: '北京', en: 'Beijing' } }, { id: 'SH', name: { zh: '上海', en: 'Shanghai' } } ], US: [ { id: 'NY', name: { zh: '纽约', en: 'New York' } }, { id: 'LA', name: { zh: '洛杉矶', en: 'Los Angeles' } } ] } export const areaCodeMapByCountry = { CN: '+86', US: '+1' }
核心联动逻辑实现
- 在Formik配置层定义三个联动字段的初始值:
initialValues = { country: '', city: '', areaCode: '' },所有字段统一纳入Formik状态管理 - 国家选择下拉的change事件作为唯一联动触发点,替代默认的纯值更新逻辑,一次完成所有关联字段的同步更新:
import { useFormik } from 'formik' import { multiLangCountryList, cityMapByCountry, areaCodeMapByCountry } from './data' const formik = useFormik({ initialValues: { country: '', city: '', areaCode: '' }, onSubmit: values => console.log('提交表单', values) }) // 国家选择change处理逻辑 const onCountrySelect = (e) => { const selectedCountryId = e.target.value // 更新国家字段值 formik.setFieldValue('country', selectedCountryId) // 匹配当前国家对应的城市列表 const relatedCities = cityMapByCountry[selectedCountryId] || [] // 自动匹配填充对应国家的电话区号 formik.setFieldValue('areaCode', areaCodeMapByCountry[selectedCountryId] || '') // 自动选中当前国家下的第一个城市 formik.setFieldValue('city', relatedCities[0]?.id || '') }
- 城市下拉的选项渲染做范围收敛:
- 不再遍历全量城市列表,直接根据当前
formik.values.country从cityMapByCountry中取出对应数组,只渲染匹配范围内的城市选项 - 每个option的label根据当前应用的全局语言环境,从城市对象的name字段中取对应语言的文本,保证多语言显示一致
- 不再遍历全量城市列表,直接根据当前
- 电话区号字段设置为只读状态:值完全由国家选择自动联动生成,不需要用户手动修改,减少操作干扰
交互细节优化
- 城市下拉和区号字段的禁用状态绑定:当
formik.values.country为空时,两个字段自动置灰禁用,直到用户选中有效国家 - 多语言切换同步:切换全局语言时,联动重新匹配当前选中国家、城市的对应语言文本,不需要用户重新触发选择动作
- 表单重置逻辑:调用Formik的reset方法时,自动清空三个联动字段的值,回到初始未选状态
- 性能优化:提前按countryId建立键值映射关系,避免每次渲染时遍历全量数据做过滤,将数据查询的时间复杂度降到O(1)
内容的提问来源于stack exchange,提问作者Yosef
相关产品推荐
相关产品推荐

