如何在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
关键修改说明
- 将
name和email放在同一个flex容器中,用flex justify-between分配空间,gap-2添加字段间距 - 修复了原代码中
handlesubmit的拼写错误,正确应为handleSubmit - 给单个字段添加
w-full类,确保输入框占满容器宽度 - 补充了提交按钮,原代码缺失导致无法提交表单
内容的提问来源于stack exchange,提问作者Safal Thapa
相关产品推荐
相关产品推荐

