首页 > web前端 > js教程 > 级联形式 React Native 改进

级联形式 React Native 改进

Barbara Streisand
发布: 2024-12-06 01:02:11
原创
488 人浏览过

我想分享我处理级联表单字段的 3 种方法。

  1. 第一个是通用方法,使用状态变量。
  2. 第二种是使用普通变量和一个布尔状态变量来触发状态效果(刷新页面)。
  3. 第三种是带有普通变量的动态表单字段。

第一种方法,使用状态变量

在这篇文章中,我们看到了第二种方法,使用普通变量来处理基于国家、州、城市数据的级联表单字段。

套餐

react-native-element-dropdown
react-native-paper
登录后复制

我们正在使用react-native-element-dropdown作为下拉字段

基页

Cascading form React Native Improved

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 (
    <View>



<p>ZDropDown is a custom component. </p>

<h3>
  
  
  Sample data
</h3>



<pre class="brush:php;toolbar:false">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 个状态变量,但这里我们使用 4 个普通变量(3 个用于下拉,1 个用于焦点字段)和一个用于切换和触发状态效果(刷新页面)的状态变量。

var country = {
  list: [],
  selectedCountry: {},
  selectedValue: null,
};

var state = {
  list: [],
  selectedState: {},
  selectedValue: null,
};

var city = {
  list: [],
  selectedCity: {},
  selectedValue: null,
};

var focusField = '';

export default function App() {
 const [refreshPage, setRefreshPage] = useState(false);

  return (
    <View>



<p>Focus and Blur events get triggered more than onChange event so it is better to maintain a separate variable to represent the focus field and avoid data mess up situations. </p>

<h3>
  
  
  Load Country
</h3>

<p>Load country dropdown from the sample data. (you can use api call)<br>
</p>

<pre class="brush:php;toolbar:false">export default function App() {
. . .
  const loadCountry = () => {
    // load data from api call
    country.list = [...listCountry];
    // switching value will refresh the ui
    setRefreshPage(!refreshPage);
  };

  useEffect(() => {
    loadCountry();
  }, []);

return (
. . .
)
登录后复制

对焦/模糊

我们使用一个函数来设置焦点字段并通过切换状态变量(refreshPage)来刷新页面

  const changeFocusField = (fld = '') => {
    focusField = fld;
    setRefreshPage(!refreshPage);
  };
登录后复制
        <Text>Country</Text>
        <ZDropDown
          . . .
          isFocus={focusField === 'country'}
          onFocus={() => changeFocusField('country')}
          onBlur={() => changeFocusField('')}
          onChange={null}
        />
        <Text>State</Text>
        <ZDropDown
        . . .
          isFocus={focusField === 'state'}
          onFocus={() => changeFocusField('state')}
          onBlur={() => changeFocusField('')}
          onChange={null}
        />
        <Text>City</Text>
        <ZDropDown        
        . . .
          isFocus={focusField === 'city'}
          onFocus={() => changeFocusField('city')}
          onBlur={() => changeFocusField('')}
          onChange={null}       
        />
登录后复制

Cascading form React Native Improved

我们现在已经完成了一半。

加载状态状态

在选择的国家/地区,我们需要根据所选国家/地区加载相应的 STATES。

更新国家/地区字段,关注国家/地区并根据国家/地区加载州。

  <Text>Country</Text>
  <ZDropDown
    . . .
    onChange={(item) => {
      country.selectedCountry = item;
      country.selectedValue = item.countryId;
      focusField = '';
      loadState();
    }}
  />
登录后复制

您看到第一种方法的区别了吗?之前更新了 3 个状态变量,但这里只更新了 1 个状态变量。

当国家/地区发生变化时,州和城市都会发生变化。因此,在设置新值之前,我们需要清除现有数据。

 const loadState = async () => {
   state = { list: [], selectedState: {}, selectedValue: null };
   city = { list: [], selectedCity: {}, selectedValue: null };
   const arr = listSate.filter(
     (ele) => ele.countryId === country.selectedValue
   );
   if (arr.length) {
     state.list = arr;
   }
   refreshPage(!refreshPage);
 };
登录后复制

Cascading form React Native Improved

负载城市

并根据国家和州加载城市字段。

    <Text>State</Text>
    <ZDropDown
      . . .
      onChange={(item) => {
        state.selectedValue = item.stateId;
        state.selectedState = item;
        changeFocusField('');
        loadCity();
      }}
     />
登录后复制
  const loadCity = async () => {
    city = { list: [], selectedCity: {}, selectedValue: null };
    const arr = listCity.filter((ele) => ele.stateId === state.selectedValue);
    if (arr.length) city.list = arr;
    setRefreshPage(!refreshPage);
  };
登录后复制

Cascading form React Native Improved

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

Cascading form React Native Improved

还有2个附加功能,一是重置页面,二是显示警告。

重置页面

表单变量和焦点变量应该被清除。

. . .
  const resetForm = () => {
    country = {list: [...listCountry],selectedCountry: {}, selectedValue: null};
    state = { list: [], selectedState: {}, selectedValue: null };
    city = { list: [], selectedCity: {}, selectedValue: null };
    focusField = '';
    setRefreshPage(!refreshPage);
  };
. . .

  <TouchableOpacity onPress={() => resetForm()}>



<h3>
  
  
  Warning
</h3>

<p>We have to show a warning msg if the parent field value is null. For that we are using SnackBar component from paper.<br>
</p>

<pre class="brush:php;toolbar:false">import { Snackbar } from "react-native-paper";
. . .
var snackMsg = '';
export default function App() {
  . . .
  const [visible, setVisible] = useState(false);

  const onToggleSnackBar = () => setVisible(!visible);
  const onDismissSnackBar = () => setVisible(false);
  . . .

  return (
    <View>



<p>We moved snackMsg to ordinary variable from state variable.</p>

<p>Since State and City fields have parent field, they have to be validated.<br>
</p>

<pre class="brush:php;toolbar:false">        <Text>State</Text>
        <ZDropDown          
          onFocus={() => {
            focusField('state');
            if (!country.selectedValue) {
              snackMsg = 'Select country';
              onToggleSnackBar();
              changeFocusField('country');
            }
          }}
          . . .
        />
        <Text>City</Text>
        <ZDropDown          
          onFocus={() => {
            focusField('city');
            if (!country.selectedValue) {
              snackMsg = 'Select country';
              onToggleSnackBar();
              changeFocusField('country');
            } else if (!state.selectedValue) {
              snackMsg = 'Select state';
              onToggleSnackBar();
              changeFocusField('state');
            }
          }}
          . . .
        />
登录后复制

Cascading form React Native Improved

完成。

谢谢。

完整代码参考这里

以上是级联形式 React Native 改进的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:dev.to
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板