You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native学校地址表单实现咨询:组件包及方案建议

Hey there! For your React Native form needs, the combo of Formik + Yup is hands down one of the most robust and user-friendly solutions out there. It handles form state management, validation, and submission flow seamlessly—perfect for your nested address structure and boolean active field. Let me walk you through a complete example:

This pair is widely adopted in React ecosystems (including React Native) because it keeps form logic clean and declarative, especially for nested data structures like your address object.

Step 1: Install Dependencies

First, add the packages to your project:

npm install formik yup
# or
yarn add formik yup

Step 2: Build the Form Component

Here’s a fully functional component that matches your required field structure. We’ll use React Native’s built-in Switch, TextInput, and Button components alongside Formik:

import React from 'react';
import { View, TextInput, Switch, Button, Text, StyleSheet } from 'react-native';
import { Formik } from 'formik';
import * as Yup from 'yup';

// Define validation rules for the form
const SchoolFormSchema = Yup.object().shape({
  active: Yup.boolean().required('Active status is required'),
  school: Yup.string().required('School name is required').min(2, 'School name must be at least 2 characters'),
  address: Yup.object().shape({
    addressLine1: Yup.string().required('Address line 1 is required'),
    addressLine2: Yup.string().nullable(), // Optional field
    city: Yup.string().required('City is required'),
    state: Yup.string().required('State is required').min(2, 'State must be at least 2 characters'),
    zip: Yup.string().required('ZIP code is required').matches(/^[0-9]{5}$/, 'ZIP code must be 5 digits'),
  }),
});

const SchoolForm = () => {
  const handleSubmit = (values) => {
    // Replace this with your actual submission logic (e.g., API call)
    console.log('Form submitted with values:', values);
    // Values will match your required structure: { active: boolean, school: string, address: {...} }
  };

  return (
    <Formik
      initialValues={{
        active: true, // Default value as per your example
        school: '',
        address: {
          addressLine1: '',
          addressLine2: '',
          city: '',
          state: '',
          zip: '',
        },
      }}
      validationSchema={SchoolFormSchema}
      onSubmit={handleSubmit}
    >
      {({ handleChange, handleBlur, handleSubmit, values, errors, touched }) => (
        <View style={styles.container}>
          {/* Active Status Toggle */}
          <View style={styles.row}>
            <Text style={styles.label}>Active:</Text>
            <Switch
              value={values.active}
              onValueChange={handleChange('active')}
              onBlur={handleBlur('active')}
            />
            {touched.active && errors.active && (
              <Text style={styles.errorText}>{errors.active}</Text>
            )}
          </View>

          {/* School Name Input */}
          <Text style={styles.label}>School Name:</Text>
          <TextInput
            style={styles.input}
            value={values.school}
            onChangeText={handleChange('school')}
            onBlur={handleBlur('school')}
            placeholder="Enter school name"
          />
          {touched.school && errors.school && (
            <Text style={styles.errorText}>{errors.school}</Text>
          )}

          {/* Address Section */}
          <Text style={styles.sectionLabel}>School Address:</Text>

          <Text style={styles.label}>Address Line 1:</Text>
          <TextInput
            style={styles.input}
            value={values.address.addressLine1}
            onChangeText={handleChange('address.addressLine1')}
            onBlur={handleBlur('address.addressLine1')}
            placeholder="123 Main St"
          />
          {touched.address?.addressLine1 && errors.address?.addressLine1 && (
            <Text style={styles.errorText}>{errors.address.addressLine1}</Text>
          )}

          <Text style={styles.label}>Address Line 2 (Optional):</Text>
          <TextInput
            style={styles.input}
            value={values.address.addressLine2}
            onChangeText={handleChange('address.addressLine2')}
            onBlur={handleBlur('address.addressLine2')}
            placeholder="Apt 4B"
          />

          <Text style={styles.label}>City:</Text>
          <TextInput
            style={styles.input}
            value={values.address.city}
            onChangeText={handleChange('address.city')}
            onBlur={handleBlur('address.city')}
            placeholder="New York"
          />
          {touched.address?.city && errors.address?.city && (
            <Text style={styles.errorText}>{errors.address.city}</Text>
          )}

          <Text style={styles.label}>State:</Text>
          <TextInput
            style={styles.input}
            value={values.address.state}
            onChangeText={handleChange('address.state')}
            onBlur={handleBlur('address.state')}
            placeholder="NY"
          />
          {touched.address?.state && errors.address?.state && (
            <Text style={styles.errorText}>{errors.address.state}</Text>
          )}

          <Text style={styles.label}>ZIP Code:</Text>
          <TextInput
            style={styles.input}
            value={values.address.zip}
            onChangeText={handleChange('address.zip')}
            onBlur={handleBlur('address.zip')}
            placeholder="10001"
            keyboardType="numeric"
          />
          {touched.address?.zip && errors.address?.zip && (
            <Text style={styles.errorText}>{errors.address.zip}</Text>
          )}

          {/* Submit Button */}
          <Button title="Submit Form" onPress={handleSubmit} />
        </View>
      )}
    </Formik>
  );
};

const styles = StyleSheet.create({
  container: {
    padding: 20,
    gap: 15,
  },
  row: {
    flexDirection: 'row',
    alignItems: 'center',
    gap: 10,
  },
  label: {
    fontSize: 16,
    fontWeight: '500',
  },
  sectionLabel: {
    fontSize: 18,
    fontWeight: 'bold',
    marginTop: 10,
  },
  input: {
    borderWidth: 1,
    borderColor: '#ccc',
    borderRadius: 8,
    padding: 10,
    fontSize: 16,
  },
  errorText: {
    color: 'red',
    fontSize: 14,
    marginTop: 5,
  },
});

export default SchoolForm;

Key Details Explained

  • Nested Field Handling: Formik makes it easy to work with nested objects using dot notation like handleChange('address.addressLine1')—no extra state management needed.
  • Validation: Yup ensures all required fields are filled and formats (like ZIP code) are correct. Error messages are displayed only when the user has interacted with a field (touched check).
  • Default Values: The initialValues object matches your required structure exactly, with active set to true as your example shows.

Alternative: React Hook Form

If you prefer a more lightweight approach with hooks, React Hook Form is another great option. It has better performance for large forms and works well with React Native. You’d use it alongside @hookform/resolvers for Yup validation:

npm install react-hook-form @hookform/resolvers yup

A basic setup would involve using the useForm hook and registering each field, following a similar pattern to the Formik example but with hook-based syntax.

Pro Tips

  • Customize the styles to match your app’s design system.
  • Add loading states to the submit button during API calls.
  • For address auto-completion, you could integrate a geocoding service (but that’s extra—your core form is fully covered with the above setup).

内容的提问来源于stack exchange,提问作者Notation

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 17:22:35