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

如何在React Formik表单中将两个输入字段置于同一行?

问题描述

我用React和Formik写了下面的表单代码,想把data数组中identiy为name和email的两个输入字段放在同一行,但目前的实现达不到这个效果。

当前代码

import React from 'react'
import {Form,Field,ErrorMessage,Formik} from 'formik'
import * as yup from 'yup'

const schema=yup.object().shape({
    cmt:yup.string().min(4,'minimun 4 words').required('comment is reqired'),
    name:yup.string().required('Name is reqired'),
    email:yup.string().required('Email is reqired'),
    website:yup.string().required('Enter website url or name'),
})

function ReplyForm() {
    const data=[
        {type:'text',placeholder:'Write a comment',identiy:'cmt'},
        {type:'text',placeholder:'Name',identiy:'name'},
        {type:'email',placeholder:'Email',identiy:'email'},
        {type:'text',placeholder:'Website',identiy:'website'},
    ]
  return (
    <div className='w-full flex justify-center'>
        <div className='w-10/12 bg-blue-200'>
            <Formik
            initialValues={{
                cmt:'',
                name:'',
                email:'',
                website:'',
            }}
            validationSchema={schema}
            onSubmit={(values)=>{
                console.log(values)
            }}
            >
                {({handlesubmit})=>{
                    return <Form onSubmit={handlesubmit}>
                        <div className='w-3/5'>
                            {data.map((val,i)=>{
                                
                                    if ((val.identiy==='name')||(val.identiy==='email')){
                                       return <div key={i} className='flex justify-between'>
                                            <Field type={val.type} name={val.identiy} placeholder={val.placeholder} className='w-1/2'/>
                                        </div>
                                    }
                                    else{
                                        return <div key={i}>
                                        <Field type={val.type} name={val.identiy} placeholder={val.placeholder}/>
                                        </div>
                                    }
                            })}
                        </div>
                    </Form>
                }}
            </Formik>
            
        </div>

    </div>
  )
}

export default ReplyForm

当前效果

当前输出效果

期望效果

期望效果


解决方案

你当前的问题在于,name和email字段各自被包裹在独立的flex容器里,所以它们会被渲染成两行。要实现同行布局,需要把这两个字段放在同一个flex容器中。

以下提供两种可直接使用的修改方案:

方案1:调整数组遍历逻辑,合并字段渲染

直接修改map循环逻辑,遇到name字段时同时渲染email,避免重复遍历:

import React from 'react'
import {Form,Field,ErrorMessage,Formik} from 'formik'
import * as yup from 'yup'

const schema=yup.object().shape({
    cmt:yup.string().min(4,'minimun 4 words').required('comment is reqired'),
    name:yup.string().required('Name is reqired'),
    email:yup.string().required('Email is reqired'),
    website:yup.string().required('Enter website url or name'),
})

function ReplyForm() {
    const data=[
        {type:'text',placeholder:'Write a comment',identiy:'cmt'},
        {type:'text',placeholder:'Name',identiy:'name'},
        {type:'email',placeholder:'Email',identiy:'email'},
        {type:'text',placeholder:'Website',identiy:'website'},
    ]
  return (
    <div className='w-full flex justify-center'>
        <div className='w-10/12 bg-blue-200 p-4'>
            <Formik
            initialValues={{
                cmt:'',
                name:'',
                email:'',
                website:'',
            }}
            validationSchema={schema}
            onSubmit={(values)=>{
                console.log(values)
            }}
            >
                {({handleSubmit})=>{
                    return <Form onSubmit={handleSubmit}>
                        <div className='w-3/5 space-y-2'>
                            {data.map((val,i)=>{
                                // 遇到name时同时渲染name和email
                                if (val.identiy==='name'){
                                    const emailField = data.find(item => item.identiy === 'email');
                                    return (
                                        <div key={i} className='flex justify-between gap-2'>
                                            <Field type={val.type} name={val.identiy} placeholder={val.placeholder} className='w-1/2'/>
                                            <Field type={emailField.type} name={emailField.identiy} placeholder={emailField.placeholder} className='w-1/2'/>
                                        </div>
                                    )
                                }
                                // 跳过email字段,避免重复渲染
                                else if (val.identiy==='email'){
                                    return null;
                                }
                                // 其他字段正常渲染
                                else{
                                    return <div key={i}>
                                        <Field type={val.type} name={val.identiy} placeholder={val.placeholder} className='w-full'/>
                                    </div>
                                }
                            })}
                        </div>
                        <button type="submit" className='mt-4 px-4 py-2 bg-blue-500 text-white'>提交</button>
                    </Form>
                }}
            </Formik>
            
        </div>
    </div>
  )
}

export default ReplyForm

方案2:重新组织字段数据,按分组渲染

把需要同行的字段归为一个分组,遍历的时候根据分组类型渲染,逻辑更清晰:

import React from 'react'
import {Form,Field,ErrorMessage,Formik} from 'formik'
import * as yup from 'yup'

const schema=yup.object().shape({
    cmt:yup.string().min(4,'minimun 4 words').required('comment is reqired'),
    name:yup.string().required('Name is reqired'),
    email:yup.string().required('Email is reqired'),
    website:yup.string().required('Enter website url or name'),
})

function ReplyForm() {
    // 重新组织数据,将同行字段归为group
    const fields = [
        { type: 'single', field: {type:'text',placeholder:'Write a comment',identiy:'cmt'} },
        { 
            type: 'group', 
            fields: [
                {type:'text',placeholder:'Name',identiy:'name'},
                {type:'email',placeholder:'Email',identiy:'email'}
            ] 
        },
        { type: 'single', field: {type:'text',placeholder:'Website',identiy:'website'} },
    ]
  return (
    <div className='w-full flex justify-center'>
        <div className='w-10/12 bg-blue-200 p-4'>
            <Formik
            initialValues={{
                cmt:'',
                name:'',
                email:'',
                website:'',
            }}
            validationSchema={schema}
            onSubmit={(values)=>{
                console.log(values)
            }}
            >
                {({handleSubmit})=>{
                    return <Form onSubmit={handleSubmit}>
                        <div className='w-3/5 space-y-2'>
                            {fields.map((item,i)=>{
                                if (item.type === 'group'){
                                    return (
                                        <div key={i} className='flex justify-between gap-2'>
                                            {item.fields.map((field,j)=>{
                                                return <Field key={j} type={field.type} name={field.identiy} placeholder={field.placeholder} className='w-1/2'/>
                                            })}
                                        </div>
                                    )
                                } else {
                                    return <div key={i}>
                                        <Field type={item.field.type} name={item.field.identiy} placeholder={item.field.placeholder} className='w-full'/>
                                    </div>
                                }
                            })}
                        </div>
                        <button type="submit" className='mt-4 px-4 py-2 bg-blue-500 text-white'>提交</button>
                    </Form>
                }}
            </Formik>
            
        </div>
    </div>
  )
}

export default ReplyForm

关键修改说明

  1. 将name和email放在同一个flex容器中,用flex justify-between分配空间,gap-2添加字段间距
  2. 修复了原代码中handlesubmit的拼写错误,正确应为handleSubmit
  3. 给单个字段添加w-full类,确保输入框占满容器宽度
  4. 补充了提交按钮,原代码缺失导致无法提交表单

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 11:17:51