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
Submit Validation Example
Submit Validation Example - Getting Started With redux-form
今回は、Submit時のエラー処理についてです。
今回はonSubmitがpropとして指定されていないので、以下のonSubmit関数(submit)をhandleSubmit()の引数として与えます。
import { SubmissionError } from 'redux-form'
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
function submit(values) {
return sleep(1000).then(() => {
// simulate server latency
if (!['john', 'paul', 'george', 'ringo'].includes(values.username)) {
throw new SubmissionError({
username: 'User does not exist', // 個別のfieldエラー
_error: 'Login failed!' // form全体のエラー
})
} else if (values.password !== 'redux-form') {
throw new SubmissionError({
password: 'Wrong password', // 個別のfieldエラー
_error: 'Login failed!' // form全体のエラー
})
} else {
window.alert(`You submitted:\n\n${JSON.stringify(values, null, 2)}`)
}
})
}
export default submit
ここで注目すべきは以下のコードです。submit関数がpromiseで、rejectで new SubmissionError({ field1: 'error', field2: 'error' }) というエラーを投げれば、それぞれのfield (field1, field2)にエラーが追加されます。下のコードではusernameのfieldにエラーが追加されます。_error は個別のfieldでなく、form全体のエラーを表示したいときに追加します。
throw new SubmissionError({
username: 'User does not exist', // 個別のfieldエラー
_error: 'Login failed!' // form全体のエラー
})
wrapped componentは以下のようになっています。this.props.onSubmitは渡されてきていないので、直接submit関数をimportし、handleSubmitの引数にしています。
import React from 'react'
import { Field, reduxForm } from 'redux-form'
import submit from './submit'
const renderField = ({ input, label, type, meta: { touched, error } }) => (
<div>
<label>{label}</label>
<div>
<input {...input} placeholder={label} type={type} />
{touched && error && <span>{error}</span>}
</div>
</div>
)
const SubmitValidationForm = props => {
const { error, handleSubmit, pristine, reset, submitting } = props
return (
// onSubmitがpropとして渡ってきていないので引数として与える
<form onSubmit={handleSubmit(submit)}>
<Field
name="username"
type="text"
component={renderField}
label="Username"
/>
<Field
name="password"
type="password"
component={renderField}
label="Password"
/>
{error && <strong>{error}</strong>}
<div>
<button type="submit" disabled={submitting}>
Log In
</button>
<button type="button" disabled={pristine || submitting} onClick={reset}>
Clear Values
</button>
</div>
</form>
)
}
export default reduxForm({
form: 'submitValidation' // a unique identifier for this form
})(SubmitValidationForm)
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)
let render = () => {
const SubmitValidationForm = require('./SubmitValidationForm').default
ReactDOM.hydrate(
<Provider store={store}>
<h2>Form</h2>
<SubmitValidationForm />
</Provider>,
dest
)
}
render()
実行結果
submitボタンをクリックしたときの画面です。
passwordエラー時の画面です。password field 個別のエラー 'Wrong password'が表示されています。加えてform全体のエラー 'Login failed!' が表示されています。
今回は以上です。