我想分享我处理级联表单字段的 3 种方法。
- 第一种方法是通用的,使用状态变量。
- 第二种是使用普通变量和一个布尔状态变量来触发状态效果(刷新页面)。
- 第三种是带有普通变量的动态表单字段。
在这篇文章中,我们看到第一种方法,即基于国家、州、城市数据处理级联表单字段的常用方法。
套餐
react-native-element-dropdown react-native-paper
我们正在使用react-native-element-dropdown作为下拉字段
基页

import react, { usestate, useeffect } from "react";
import { view, text, stylesheet, touchableopacity } from "react-native";
import { dropdown } from "react-native-element-dropdown";
export default function app() {
return (
country
state
city
selected country
{country.selectedcountry.name}
selected state
{state.selectedstate.name}
selected city
{city.selectedcity.name}
reset
);
}
const zdropdown = ({
data,
labelfield,
valuefield,
value,
onfocus,
onblur,
onchange,
isfocus,
}) => {
return (
5}
maxheight={300}
searchplaceholder="search..."
data={data}
labelfield={labelfield}
valuefield={valuefield}
placeholder={!isfocus ? "select item" : "..."}
value={value}
onfocus={onfocus}
onblur={onblur}
onchange={onchange}
/>
);
};
const styles = stylesheet.create({
// style props
});
zdropdown 是一个自定义组件。
样本数据
const listcountry = [
{ countryid: "1", name: "india" },
{ countryid: "2", name: "uk" },
{ countryid: "3", name: "canada" },
{ countryid: "4", name: "us" },
];
const listsate = [
{ stateid: "1", countryid: "1", name: "state1_india" },
{ stateid: "4", countryid: "2", name: "state1_uk" },
{ stateid: "7", countryid: "3", name: "state1_canada" },
{ stateid: "10", countryid: "4", name: "state1_us" },
];
const listcity = [
{
cityid: "1",
stateid: "1",
countryid: "1",
name: "city1_state1_country1",
},
{
cityid: "6",
stateid: "2",
countryid: "1",
name: "city6_state2_country1",
},
{
cityid: "7",
stateid: "3",
countryid: "1",
name: "city7_state3_country1",
},
{
cityid: "23",
stateid: "8",
countryid: "3",
name: "city23_state8_country3",
},
{
cityid: "30",
stateid: "10",
countryid: "4",
name: "city30_state10_country4",
},
{
cityid: "35",
stateid: "12",
countryid: "4",
name: "city35_state12_country4",
},
{
cityid: "36",
stateid: "12",
countryid: "4",
name: "city36_state12_country4",
},
];
表单变量
我们使用 4 个状态变量,其中 3 个用于表单字段,其余一个用于触发焦点效果。
export default function app() {
const [country, setcountry] = usestate({
data: [],
selectedcountry: {},
value: null,
});
const [state, setstate] = usestate({
data: [],
selectedstate: {},
value: null,
});
const [city, setcity] = usestate({ data: [], selectedcity: {}, value: null });
const [ddfocus, setddfocus] = usestate({
country: false,
state: false,
city: false,
});
return (
country
state
city
. . .
);
}
焦点和模糊事件比 onchange 事件更容易被触发,因此对于焦点更改,这里使用一个单独的状态变量,以免弄乱下拉数据更改。
负载国家
从示例数据中加载国家/地区下拉列表。 (可以使用api调用)
export default function app() {
. . .
const loadcountry = () => {
// load data from api call
setcountry({ data: [...listcountry], selectedcountry: {}, value: null });
};
useeffect(() => {
loadcountry();
}, []);
return (
. . .
)
对焦/模糊
当选择一个下拉菜单时,该字段必须被聚焦,而其余字段应该被模糊。我们正在使用一个函数来处理这个问题。
const focusfield = (fld = '') => {
const obj = { country: false, state: false, city: false };
if (fld) obj[fld] = true;
setddfocus(obj);
};
country focusfield('country')} onblur={() => focusfield('')} onchange={null} /> state focusfield('state')} onblur={() => focusfield('')} onchange={null} /> city focusfield('city')} onblur={() => focusfield('')} onchange={null} />

我们现在已经完成了一半。
加载状态状态
在选择的国家/地区,我们需要根据所选国家/地区加载相应的州 states。
更新国家/地区字段,根据国家/地区选择加载州并关注国家/地区。
country { setcountry({ ...country, selectedcountry: item, value: item.countryid, }); loadstate(item.countryid); focusfield(""); }} />
当国家/地区发生变化时,州和城市都会发生变化。因此,在设置新值之前,我们需要清除现有数据。
const loadstate = async (cntid) => {
// load data from api call
setstate({ data: [], selectedstate: {}, value: null });
setcity({ data: [], selectedcity: {}, value: null });
const arr = listsate.filter((ele) => ele.countryid === cntid);
setstate({ ...state, data: [...arr] });
console.log("respective states ", arr);
};

负载城市
并根据选择加载城市字段。
state { setstate({ ...state, selectedstate: item, value: item.stateid }); loadcity(item.stateid); focusfield(""); }} />
const loadcity = async (stid) => {
// load data from api call
setcity({ data: [], selectedcity: {}, value: null });
const arr = listcity.filter((ele) => ele.stateid === stid);
setcity({ ...city, data: [...arr] });
};

一切就绪,表单字段现在可以正常工作了。

如果我们再处理 2 个附加功能,我们就完成了。一种是休息页面,另一种是验证表单并显示警告。
重置页面
表单变量和焦点变量应该被清除。
. . .
const resetform = () => {
focusfield("");
setcountry({ data: [...listcountry], selectedcountry: {}, value: null });
setstate({ data: [], selectedstate: {}, value: null });
setcity({ data: [], selectedcity: {}, value: null });
};
. . .
resetform()} style={styles.clrbtn}>
reset
. . .
警告
如果父字段值为空,我们必须显示警告消息。为此,我们使用 paper 中的 snackbar 组件。
import { snackbar } from "react-native-paper";
export default function app() {
. . .
const [visible, setvisible] = usestate(false);
const [snackmsg, setsnackmsg] = usestate("");
const ontogglesnackbar = () => setvisible(!visible);
const ondismisssnackbar = () => setvisible(false);
. . .
return (
. . .
{snackmsg}
);
}
由于 state 和 city 字段有父字段,因此必须验证它们。
State { focusField('state'); if (!country.value) { setSnackMsg('Select country'); onToggleSnackBar(); focusField('country'); } }} . . . /> City { focusField('city'); if (!country.value) { setSnackMsg('Select country'); onToggleSnackBar(); focusField('country'); } else if (!state.value) { setSnackMsg('Select state'); onToggleSnackBar(); focusField('state'); } }} . . . />

是的,就是这样!我们完成了。谢谢。
完整代码参考这里










