redux-form (1) - Simple Form Example
redux-form (2) - Synchronous Validation Example
redux-form (3) - Field-Level Validation Example
redux-form (4) - Submit Validation Example
redux-form (5) - Initialize From State
redux-form (6) - ユーザ登録
ReactでForm componentを作るときに、とても便利な**redux-form**の説明です。
redux-formの概説についてはまず以下の記事を参考にしてください。
redux-form (1) - Simple Form Example
Field-Level Validation Example
redux-form (2) - Synchronous Validation Exampleでは、Redux state 全体のvaluesを入力として、errorのobjectを返す、validate関数でのチェックの方法を見ました。1個のvalidate関数で全Formのvalidateを行いました。
今回は、各Fieldを個別に validate する方法を紹介します。各Field毎に、validate propとしてvalidate関数を指定します。validate関数はFieldのvalueを入力にとり、value が valid であればundefineを返し、value が invalid であればエラーメッセージ(文字列)を返します。 小さく再利用可能なvalidate関数を作ることで、同じようなコードを何回も書くことを避けることができるメリットがあります。
Field-Level Validation Example - Getting Started With redux-form
以下のソースコードを見てください。
最初に小さなvalidate関数を多数定義しています。
それをField componentの validate prop に指定します。
例えばrequiredは複数のField componentで指定されています。一度定義すれば、再利用可能なので同じコードを繰り返す必要がなくなります。
import React from 'react'
import { Field, reduxForm } from 'redux-form'
const required = value => (value || typeof value === 'number' ? undefined : 'Required')
const maxLength = max => value =>
value && value.length > max ? `Must be ${max} characters or less` : undefined
const maxLength15 = maxLength(15)
export const minLength = min => value =>
value && value.length < min ? `Must be ${min} characters or more` : undefined
export const minLength2 = minLength(2)
const number = value =>
value && isNaN(Number(value)) ? 'Must be a number' : undefined
const minValue = min => value =>
value && value < min ? `Must be at least ${min}` : undefined
const minValue13 = minValue(13)
const email = value =>
value && !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(value)
? 'Invalid email address'
: undefined
const tooYoung = value =>
value && value < 13
? 'You do not meet the minimum age requirement!'
: undefined
const aol = value =>
value && /.+@aol\.com/.test(value)
? 'Really? You still use AOL for your email?'
: undefined
const alphaNumeric = value =>
value && /[^a-zA-Z0-9 ]/i.test(value)
? 'Only alphanumeric characters'
: undefined
export const phoneNumber = value =>
value && !/^(0|[1-9][0-9]{9})$/i.test(value)
? 'Invalid phone number, must be 10 digits'
: undefined
const renderField = ({
input,
label,
type,
meta: { touched, error, warning }
}) => (
<div>
<label>{label}</label>
<div>
<input {...input} placeholder={label} type={type} />
{touched &&
((error && <span>{error}</span>) ||
(warning && <span>{warning}</span>))}
</div>
</div>
)
const FieldLevelValidationForm = props => {
const { handleSubmit, pristine, reset, submitting } = props
return (
<form onSubmit={handleSubmit}>
<Field
name="username"
type="text"
component={renderField}
label="Username"
validate={[required, maxLength15, minLength2]}
warn={alphaNumeric}
/>
<Field
name="email"
type="email"
component={renderField}
label="Email"
validate={email}
warn={aol}
/>
<Field
name="age"
type="number"
component={renderField}
label="Age"
validate={[required, number, minValue13]}
warn={tooYoung}
/>
<Field
name="phone"
type="number"
component={renderField}
label="Phone number"
validate={[required, phoneNumber]}
/>
<div>
<button type="submit" disabled={submitting}>
Submit
</button>
<button type="button" disabled={pristine || submitting} onClick={reset}>
Clear Values
</button>
</div>
</form>
)
}
export default reduxForm({
form: 'fieldLevelValidation' // a unique identifier for this form
})(FieldLevelValidationForm)
以下は、オリジナルなものを最小化したindex.jsです。
import React from 'react'
import ReactDOM from 'react-dom'
import { Provider } from 'react-redux'
import { createStore, combineReducers } from 'redux'
import { reducer as reduxFormReducer } from 'redux-form'
const dest = document.getElementById('content')
const reducer = combineReducers({
form: reduxFormReducer // mounted under "form"
})
const store = createStore(reducer)
const showResults = values =>
new Promise(resolve => {
setTimeout(() => {
// simulate server latency
window.alert(`You submitted:\n\n${JSON.stringify(values, null, 2)}`)
resolve()
}, 500)
})
let render = () => {
const FieldLevelValidationForm = require('./FieldLevelValidationForm').default
ReactDOM.hydrate(
<Provider store={store}>
<h2>Form</h2>
<FieldLevelValidationForm onSubmit={showResults} />
</Provider>,
dest
)
}
render()
実行画面
エラー表示
今回は以上です。