LoginSignup
16
18

More than 1 year has passed since last update.

Reactでリアクティブなvalidationフォームの作成

Last updated at Posted at 2020-08-15

作りたいもの

Reactだけでデータが入力されたタイミングでバリデーションを実行するフォームの実装。エラーが存在する場合はエラー内容を表示し、ボタンをdisabledにする。
スクリーンショット 2020-08-15 17.12.32.png

完成形

import React from 'react';
import ReactDOM from 'react-dom';

class Form extends React.Component{
    constructor(props){
        super(props);
        this.state = {
            info: {
                email: '',
                content: ''
            },
            message:{
                email: '',
                content: ''
            }
        };
        this.handleChange = this.handleChange.bind(this);
    }

    handleChange(event) {
        const name = event.target.name;
        const value = event.target.value;
        const { info, message } = this.state;
        this.setState({
            info: { ...info, [name]: value }
        });
        this.setState({
            message: {...message,[name]: this.validator(name, value)}
        });
    }

    validator(name, value){
        switch (name) {
            case 'email':
            return this.emailValidation(value);
            case 'content':
            return this.contentValidation(value);
        }
    }

    emailValidation(value){
        if (!value) return '※メールアドレスを入力してください';
        const regex = /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/;
        if (!regex.test(value)) return '※正しい形式でメールアドレスを入力してください';
        return '';
    }

    contentValidation(value){
        if (!value) return '※内容を入力してください';
        if (value.length < 8) return '※内容は8文字以上で入力してください';
        return '';
    }

    render(){
        const { info, content } = this.state;
        return (
            <div>
            <p>メールアドレス必須</p>
            <p>{this.state.message.email}</p>
            <input type="text" name="email" value={this.state.info.email} onChange={this.handleChange} size="30" />
            <p>お問い合わせ内容必須</p>
            <p>{this.state.message.content}</p>
            <textarea name="content" onChange={this.handleChange} defaultValue={this.state.info.content} cols="50" rows="5"></textarea>
            <input type="submit" value="送信する"
            disabled={!this.state.info.email || !this.state.info.content || this.state.message.email || this.state.message.content } />
            </div>
        );
    }
}

export default Form;


if (document.getElementById('app')) {
    ReactDOM.render(
        <Form />,
        document.getElementById('app')
    );
}

解説

inputで入力されたデータを「info」、エラーメッセージを「message」でstate管理します。
bindするのはお忘れなく。

constructor(props){
    super(props);
    this.state = {
        info: {
            email: '',
            content: ''
        },
        message:{
            email: '',
            content: ''
        }
    };
    this.handleChange = this.handleChange.bind(this);
}

inputから入力されたデータをstateに渡します。このタイミングでvalidatorメソッドを呼び出し、エラーが存在する場合はmessageに格納します。

handleChange(event) {
    const name = event.target.name;
    const value = event.target.value;
    const { info, message } = this.state;
    this.setState({
        info: { ...info, [name]: value }
    });
    this.setState({
        message: {...message,[name]: this.validator(name, value)}
    });
}

inputのnameによって呼び出す関数を指定します。今回はメールアドレスが正しいメールアドレス形式にされているか正規表現と、お問い合わせ内容が指定した文字以上になっているかをチェックします。

validator(name, value){
    switch (name) {
        case 'email':
        return this.emailValidation(value);
        case 'content':
        return this.contentValidation(value);
    }
}

emailValidation(value){
    if (!value) return '※メールアドレスを入力してください';
    const regex = /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/;
    if (!regex.test(value)) return '※正しい形式でメールアドレスを入力してください';
    return '';
}

contentValidation(value){
    if (!value) return '※内容を入力してください';
    if (value.length < 8) return '※内容は8文字以上で入力してください';
    return '';
}

データが入力されていない、もしくはエラーメッセージが存在する場合は、ボタンのdisabledをtrueにします。

<input type="submit" value="送信する" 
disabled={!this.state.info.email || !this.state.info.content || this.state.message.email || this.state.message.content } />
16
18
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
18