かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

TypeScript + Reactでredux-formを使って非同期の検証処理を行う

1つ前の記事で同期的な検証をやりました。redux-formは非同期な検証処理もサポートしています。

使い方は簡単、Primiseを返す検証ロジックを作って、reduxFormメソッドを呼び出すときasyncValidateに渡すだけ。非同期の検証のロジックのトリガーとなるフィールドの名前を渡すこともできます。こいつらを指定すると、フォーカス外れたタイミングあたりで検証ロジックが呼び出されるようになります。

コードとしてはこんな感じです。前回とほとんど変わりありませんね。

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import * as ReduxForm from 'redux-form';
import * as Redux from 'redux';
import {Provider} from 'react-redux';

interface MyFormFields {
    x: string;
    y: string;
}

interface MyFormProps extends ReduxForm.ReduxFormProps {
    onSubmit: (data: MyFormFields) => void;
}

class MyForm extends React.Component<MyFormProps, {}> {
    render() {
        const {
            handleSubmit,
            fields: {x, y}
        } = this.props;
        return (
            <form onSubmit={handleSubmit}>
                <div>
                    <input type='text' {...x} />{x.error && <span>{x.error}</span>}
                </div>
                <div>
                    <input type='text' {...y} />{y.error && <span>{y.error}</span>}
                </div>
                <input type='submit' />
            </form>
        );
    }
}

// 検証用関数
function validateContent(values: MyFormFields): Promise<MyFormFields> {
    return new Promise<MyFormFields>((resolve, reject) => {
        setTimeout(() => {
            var result = {} as MyFormFields;
            if(!values.x) {
                result.x = 'xを入力してね';
            }
            if (!values.y) {
                result.y = 'yを入力してね';
            }

            resolve(result);
        }, 5000);
    });
}

const SampleForm = ReduxForm.reduxForm({
    form: 'sample',
    fields: ['x', 'y'],
    asyncValidate: validateContent, // formを作るときに渡す
    asyncBlurFields: ['x', 'y'] // フォーカス外れた時に検証処理走らせるフィールド
})(MyForm);

const reducer = Redux.combineReducers({
    form: ReduxForm.reducer
});
const store = Redux.createStore(reducer);

function handle(e: MyFormFields) {
    alert(e.x + ', ' + e.y);
}

ReactDOM.render(
    <Provider store={store}>
        <SampleForm onSubmit={handle}/>
    </Provider>,
    document.getElementById('content'));