公式の Semantic UI React コンポーネントを使用してWebアプリケーションを作成しています。サインアップページに、メールフィールド、パスワードフィールド、パスワードの確認フィールドを含むフォームがあります。
import {Component} from 'react';
import {Button, Form, Message} from 'semantic-ui-react';
import {signUp} from '../../actions/auth';
class SignUp extends Component {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(e, {formData}) {
e.preventDefault();
//
// Potentially need to manually validate fields here?
//
// Send a POST request to the server with the formData
this.props.dispatch(signUp(formData)).then(({isAuthenticated}) => {
if (isAuthenticated) {
// Redirect to the home page if the user is authenticated
this.props.router.Push('/');
}
}
}
render() {
const {err} = this.props;
return (
<Form onSubmit={this.handleSubmit} error={Boolean(err)}>
<Form.Input label="Email" name="email" type="text"/>
<Form.Input label="Password" name="password" type="password"/>
<Form.Input label="Confirm Password" name="confirmPassword" type="password"/>
{err &&
<Message header="Error" content={err.message} error/>
}
<Button size="huge" type="submit" primary>Sign Up</Button>
</Form>
);
}
}
今、私は通常のセマンティックUIライブラリに慣れています。これには Form Validationアドオン があります。通常、このようなルールは別のJavaScriptファイルで定義します
$('.ui.form').form({
fields: {
email: {
identifier: 'email',
rules: [{
type: 'empty',
Prompt: 'Please enter your email address'
}, {
type: 'regExp',
value: "[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?",
Prompt: 'Please enter a valid email address'
}]
},
password: {
identifier: 'password',
rules: [{
type: 'empty',
Prompt: 'Please enter your password'
}, {
type: 'minLength[8]',
Prompt: 'Your password must be at least {ruleValue} characters'
}]
},
confirmPassword: {
identifier: 'confirmPassword',
rules: [{
type: 'match[password]',
Prompt: 'The password you provided does not match'
}]
}
}
});
フォームを検証するためのセマンティックUI Reactコンポーネントを使用した同様のメソッドはありますか?ドキュメントを検索しても成功せず、このセマンティックを使用した検証の例はないようですUI Reactライブラリ。
代わりに、handleSubmit
関数で各フィールドを手動で検証する必要がありますか?この問題を修正する最良の方法は何ですか?助けてくれてありがとう!
ほとんどの場合、フォームを手動で検証する必要があります。ただし、RSUIには、物事を少し簡単にするいくつかのツール、特に_<Form>
_および_<Form.Input>
_のエラープロパティが含まれています
ここに、最近私がまとめたフォームの例を示します。少しのリファクタリングを使用できますが、基本的に各入力をonChange()
関数で状態に結び付け、ロード画面と「成功」の可視性を制御するサブミット関数にコールバックを渡すことで機能します。フォームの一部を送信していただきありがとうございます。
_export default class MeetingFormModal extends Component {
constructor(props) {
super(props)
this.state = {
firstName: '',
lastName: '',
email: '',
location: '',
firstNameError: false,
lastNameError: false,
emailError: false,
locationError: false,
formError: false,
errorMessage: 'Please complete all required fields.',
complete: false,
modalOpen: false
}
this.submitMeetingForm = this.submitMeetingForm.bind(this);
this.successCallback = this.successCallback.bind(this);
}
successCallback() {
this.setState({
complete: true
})
setTimeout( () => {this.setState({modalOpen: false})}, 5000);
this.props.hideLoading();
}
handleClose = () => this.setState({ modalOpen: false })
handleOpen = () => this.setState({ modalOpen: true })
submitMeetingForm() {
let error = false;
if (this.state.studentFirstName === '') {
this.setState({firstNameError: true})
error = true
} else {
this.setState({firstNameError: false})
error = false
}
if (this.state.studentLastName === '') {
this.setState({lastNameError: true})
error = true
} else {
this.setState({lastNameError: false})
error = false
}
if (this.state.email === '') {
this.setState({emailError: true})
error = true
} else {
this.setState({emailError: false})
error = false
}
if (this.state.location === '') {
this.setState({locationError: true})
error = true
} else {
this.setState({locationError: false})
error = false
}
if (error) {
this.setState({formError: true})
return
} else {
this.setState({formError: false})
}
let meeting = {
first_name: this.state.firstName,
last_name: this.state.lastName,
email: this.state.email,
location: this.state.location,
this.props.createMeeting(meeting, this.successCallback)
this.props.showLoading();
}
capitalize(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
render() {
return(
<Modal
trigger={<Button onClick={this.handleOpen} basic color='blue'>Schedule Now</Button>}
open={this.state.modalOpen}
onClose={this.handleClose}
closeIcon={true}
>
<Modal.Header>Schedule Your Interview</Modal.Header>
<Modal.Content>
{!this.state.complete ?
<Modal.Description>
<Form error={this.state.formError}>
<Form.Group widths='equal'>
<Form.Field>
<Form.Input required={true} onChange={(e) => this.setState({firstName: e.target.value})} label='First Name' placeholder="First Name..." error={this.state.firstNameError}/>
</Form.Field>
<Form.Field>
<Form.Input required={true} onChange={(e) => this.setState({lastName: e.target.value})} label='Last Name' placeholder="Last Name..." error={this.state.lastNameError}/>
</Form.Field>
</Form.Group>
<Form.Field >
<Form.Input required={true} onChange={(e) => this.setState({email: e.target.value})} label='Email' placeholder="Email..." error={this.state.emailError}/>
</Form.Field>
<Form.Field>
<Form.Input required={true} onChange={(e) => this.setState({location: e.target.value})} label='Location' placeholder='City, State/Province, Country...' error={this.state.locationError}/>
</Form.Field>
</Form>
</Modal.Description>
:
<div className='modal-complete'>
<Image src='/images/check.png' />
<p>Thanks for scheduling a meeting, {this.capitalize(this.state.name)}. We've received your information and we'll be in touch shortly.</p>
</div>
}
</Modal.Content>
{!this.state.complete ?
<Modal.Actions>
<Button color='red' onClick={this.handleClose}>Close</Button>
<Button positive icon='checkmark' labelPosition='right' content="Submit" onClick={this.submitMeetingForm} />
</Modal.Actions>
: null }
</Modal>
)
}
}
_
お役に立てば幸いです!
優れたオプションもありますが、semantic-ui-reactでは提供されていません-> Formik + yup
Formik:フォーム状態の管理に役立ちますYup:その状態の検証に役立ちます
基本的に、semantic-ui-reactを使用して作成された編集フォームである以下のコンポーネントがあります。
import React, { Component } from "react";
import { Button, Form, Modal, Message, Divider } from "semantic-ui-react";
import { Formik } from "formik";
import * as yup from "yup";
class EditAboutGrid extends Component {
render() {
const {
userBasic,
editBasicModal,
closeModal
} = this.props;
return (
<Formik
initialValues={{
firstName: userBasic.firstName,
lastName: userBasic.lastName,
bio: userBasic.bio,
}}
validationSchema={yup.object().shape({
firstName: yup
.string()
.required("Name cannot be empty"),
lastName: yup
.string()
.required("Name cannot be empty"),
bio: yup
.string()
.max(1000, "Maximum characters exceed 1000")
.nullable()
})}
onSubmit={(values, actions) => {
//do your stuff here like api calls
}}
render={({
values,
errors,
handleChange,
handleSubmit,
isSubmitting,
dirty,
setFieldValue
}) => (
<Modal open={editBasicModal} size="small">
<Modal.Header>Your basic details</Modal.Header>
<Modal.Content scrolling>
{errors.firstName && <Message error content={errors.firstName} />}
{errors.lastName && <Message error content={errors.lastName} />}
{errors.bio && <Message error content={errors.bio} />}
<Form loading={isSubmitting}>
<Form.Group inline widths="equal">
<Form.Input
required
label="First Name"
fluid
type="text"
name="firstName"
value={values.firstName}
onChange={handleChange}
error={errors.firstName !== undefined}
/>
<Form.Input
required
label="Last Name"
fluid
type="text"
name="lastName"
value={values.lastName}
onChange={handleChange}
error={errors.lastName !== undefined}
/>
</Form.Group>
<Form.TextArea
label="Bio"
type="text"
name="bio"
value={values.bio}
onChange={handleChange}
rows={3}
error={errors.bio !== undefined}
/>
</Form>
</Modal.Content>
<Modal.Actions open={true}>
<Button
onClick={() => (dirty ? closeModal(true) : closeModal(false))}>
Cancel
</Button>
<Button
primary
type="submit"
onClick={handleSubmit}
loading={isSubmitting}
disabled={isSubmitting || !isEmpty(errors) || !dirty}>
Update
</Button>
</Modal.Actions>
</Modal>
)}
/>
);
}
}
そして、このフォームは次を使用して呼び出されます:
<EditAboutGrid
editBasicModal={this.state.editBasicModal}
userBasic={this.state.user.basic}
closeModal={this.closeModal}
/>
initialValues
は、物事が始まる場所です。ここで、フォームの入力に初期値/デフォルト値を渡します。 values
(in form)は、このデフォルトからデータ値を選択します。
validationSchema
は、yup
を使用してすべての検証が行われる場所です
onSubmit
はフォーム送信時に呼び出されます。
Formik + yupを使用したフォームの処理は非常に簡単です。大好き。
代わりに、handleSubmit関数で各フィールドを手動で検証する必要がありますか?
悲しいけれど事実です。 SUIR 持っていない 現在フォーム検証。ただし、HOCを使用して redux-form などのフォームを操作できます。
以下のコードは、基本的に各コンポーネント名と関連する値に状態を設定します。 (IE、状態は{marketSide:buy、price:50、quantity:9}のようになります。フォームエラー情報も状態に詰め込み、yupのデフォルト動作を利用して、検証スキーマで言及されていないフィールドを検証しません。 。
重要なポイント:
1)schema.validate(someObjectToValidate、yupProperties)の呼び出し(someObjectToValidateはthis.stateのみ)で、プロパティオブジェクトとして{abortEarly:false}を渡して、単一エラーが発生したときに検証を停止するyupsのデフォルト動作をオーバーライドする必要がありますフォームのメッセージコンポーネントがすべてのエラーをユーザーに表示するため、発生しました。
2)yup検証が失敗した場合、yupは例外をスローするため、例外をキャッチし、関心のあるエラー情報を選択して、このエラーで状態を更新します。
3)setStateは非同期であるため、this.setState(...)の「コールバックフォーム」を使用する必要があります。これにより、状態オブジェクトの検証は、状態が更新された後にのみ行われます。
4)yup検証が成功した場合、エラーとerrorPath配列をクリアします。
5)これは簡単な解決策です。レンダリングごとにerrorPaths配列を数回チェックしています。現在のソリューション(2配列* Nフィールド* N潜在的エラー= O(2n ^ 2))を改善するために、2つの配列ではなく、コンポーネントの名前をキーとするjsonオブジェクトにerrorPathとエラー情報を保存する方が良いでしょうパフォーマンス。
6)長いスタイルの '<Form.Field control={Radio}>
'表記を無視して、短い<Input>, <Button>, <Radio>,
などのスタイルを使用できます。この構文は検証とは関係ありません。 divも無視します。
import React, { Component } from 'react'
import { Button, Checkbox, Form, Input, Radio, Select, Message, Label } from 'semantic-ui-react'
import * as yup from 'yup';
const options = [
{ text: 'buy', value: 'buy' },
{ text: 'sell', value: 'sell' },
]
class OrderEntryV3 extends Component {
state = {
errorPaths:[],
errors:[]
}
constructor(props){
super(props);
}
schema = yup.object().shape({
quantity: yup.number().required().positive().integer(),
price: yup.number().required().positive(),
marketSide: yup.string().required(),
orderType : yup.string().required()
});
handleChange = (e, component) => {
this.setState({[component.name]:component.value}, ()=>this.schema.validate(this.state, {abortEarly:false})
.then(valid=>this.setState({errorPaths:[], errors:[]})) //called if the entire form is valid
.catch(err=>this.setState({errors:err.errors, errorPaths: err.inner.map(i=>i.path) }))) //called if any field is invalid
};
render() {
return (
<div id="oeform-content">
<div id="oeform-left">
<Form>
<Form.Field error={this.state.errorPaths.includes('marketSide')} name="marketSide" control={Select} label='Market side' options={options} placeholder='market side' onChange={this.handleChange}/>
<Form.Field error={this.state.errorPaths.includes('quantity')} type='number' name="quantity" control={Input} label='Quantity' placeholder='quantity' onChange={this.handleChange}/>
<Form.Group>
<label><b>Order type</b></label>
<Form.Field error={this.state.errorPaths.includes('orderType')} >
<Radio
label='market'
name='orderType'
value='market'
checked={this.state.orderType === 'market'}
onChange={this.handleChange}
/>
</Form.Field>
<Form.Field error={this.state.errorPaths.includes('orderType')}>
<Radio
label='limit'
name='orderType'
value='limit'
checked={this.state.orderType === 'limit'}
onChange={this.handleChange}
/>
</Form.Field>
</Form.Group>
<Form.Field error={this.state.errorPaths.includes('price')} name='price' control={Input} type='number' label='Price' placeholder='price' onChange={this.handleChange}/>
<Form.Field control={Button} disabled={!!this.state.errors.length}>Submit</Form.Field>
<Message visible={!!this.state.errors.length} warning
header='Please correct the following issues: '
list={this.state.errors}/>
</Form>
</div>
<div id="oeform-right">
<p>{JSON.stringify(this.state)}</p>
</div>
</div>
)
}
}
export default OrderEntryV3
検証にはプラグインを使用できます。プラグイン名: formsy-semantic-ui-react