かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

TypeScriptでredux-formを使ってみる

入力フォームを作るのに便利そうなredux-formというのがあります。

erikras.github.io

TypeScriptの型定義もあるので使ってみました。とりあえずシンプルな例から。

redux-formを使うには、reducerでReduxFormのreducerをformという名前でcombineReducersしてやる必要があります。

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

次に、formの定義です。formをラップするコンポーネントは、ReduxFormPropsを拡張したインターフェースをプロパティに指定します。こいつのhandleSubmitにコード例にあるように外部から呼び出せるようにonSubmitを渡してやるといい感じにデータをつめて渡してくれます。

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(this.props.onSubmit)}>
                <div>
                    <input type='text' {...x} />
                </div>
                <div>
                    <input type='text' {...y} />
                </div>
                <input type='submit' />
            </form>
        );
    }
}

reduxFormメソッドで、formをラップしたコンポーネントを、名前(ここではsample)をつけて登録します。名前は一意である必要があるっぽいです。

const SampleForm = ReduxForm.reduxForm({
    form: 'sample',
    fields: ['x', 'y']
})(MyForm);

onSubmitには、formの各inputタグの中身がいい感じに入ってきてくれます。

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

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

コード全体

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(this.props.onSubmit)}>
                <div>
                    <input type='text' {...x} />
                </div>
                <div>
                    <input type='text' {...y} />
                </div>
                <input type='submit' />
            </form>
        );
    }
}

const SampleForm = ReduxForm.reduxForm({
    form: 'sample',
    fields: ['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'));