Reactでエラーメッセージを表示する

# プログラミングの勉強日記
2020年6月24日　Progate Lv.148
React Ⅳ
　[前回の記事](https://qiita.com/mzmz__02/items/edb12732a7de374af8d6) で作成した問い合わせフォームにエラーメッセージを表示させる。今回は簡単なエラーメッセージを作成する。

##入力内容をstateで管理する
　入力に合わせてエラーメッセージを表示する処理を作る。エラーメッセージは文字を入力してから入力値が空ならエラーが表示されるようにする。

###1.stateでinputの準備
　Reactでフォームを作る場合、stateと入力値を紐づける。メールアドレスの入力値を管理するstateのemailを用意して、inputタグのvalue属性にstateの値を指定する。

```react:ContactForm.js
  super(props);
  this.state={
    ...
    email:'', //入力値を管理するstateを準備
  };
  return(
    {/* value属性にstateの値を指定。フォームの入力欄にstateの値が表示される */}
    <input value={this.state.email} />
  );
```

###2.入力イベントの取得
　このままだと入力できないので入力できるようにする。
　フォームの入力や削除が行われたときに処理を実行するにはonChangeイベントを使う。

```react:ContactForm.js
<input onChange={()=>{/*処理*/}} />
```
　入力値の取得はonChangeイベントの関数にeventという引数を追加して`event.target.value`で取得する。

```react:ContactForm.js
<input 
  value={this.state.email}
  onChange={(event)=>{console.log(event.target.value)}}
/>
```

###3.stateの更新
　handleEmailChangeメソッドを作ってstateの更新を行う。

```react:ContactForm.js
handleEmailChange(event){
  const inputValue=event.target.value;  //2.入力値を取得
  this.setState({email:inputValue});  //3.入力値でstateを更新
}
...
retuen(
  <p>メールアドレス</p>
  <input 
    value={this.state.email}
    onChange={(event)=>
      {/* 1.eventを引数に渡してメソッドを呼び出す */}
      {this.handleEmailChange(event)}
    } 
  >
);
```

##エラーメッセージの作成
　入力欄に文字を入力してから文字の入力を全て消したときにエラーメッセージが出るようにする。入力値が空かどうかをstateで管理する。stateで新たにhasEmailErrorという真偽値型のstateを定義する。

```react:ContactForm.js
constructor(props){
  super(props);
  this.state={
    ...
    hasEmailError:false,
  };
}
```
　hasEmailErrorがtrueのとき変数emailErrorTextにエラー部分のJSXを代入して表示する。

```react:ContactForm.js
render(){
  let emailErrorText;
  if(this.state.hasEmailError){
    emailErrorText=(
      <p>メールアドレスを入力してください</p>
    );
  }
  ...
  return(
    <p>メールアドレス（必須）</p>
    <input 
      value={this.state.email}
      ...
      {emailErrorText}
```
　エラーメッセージを表示する。入力値と空文字列(`''`)を比較して、`isEmpty`に代入する。複数のstateを更新する場合、コンマ(`,`)で区切り一度の`setState`でまとめて変更することができる。

```react:ContactForm.js
handleEmailChange(event){
  const inputValue=event.target.value;
  const isEmpty=inputValue==='';
  this.setState({
    email:inputValue,
    hasEmailError:isEmpty,
  });
}
```


##問い合わせフォームでエラーメッセージの表示

```react:ContactForm.js
import React from 'react';

class ContactForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isSubmitted: false,
      email: '',
      hasEmailError: false,
    };
  }

  handleEmailChange(event) {
    const inputValue = event.target.value;
    const isEmpty=inputValue==='';
    
    this.setState({
      email:inputValue,
      hasEmailError:isEmpty,
    });
    
  }

  handleSubmit() {
    this.setState({isSubmitted: true});
  }

  render() {
    let emailErrorText;
    if (this.state.hasEmailError) {
      emailErrorText = (
        <p className='contact-message-error'>
          メールアドレスを入力してください
        </p>
      );
    }

    let contactForm;
    if (this.state.isSubmitted) {
      contactForm = (
        <div className='contact-submit-message'>
          送信完了
        </div>
      );
    } else {
      contactForm = (
        <form onSubmit={() => {this.handleSubmit()}}>
          <p>メールアドレス（必須）</p>
          <input
            value={this.state.email}
            onChange={(event) => {this.handleEmailChange(event)}}
          />
          {emailErrorText}
          <p>お問い合わせ内容（必須）</p>
          <textarea />
          <input
            type='submit'
            value='送信'
          />
        </form>
      );
    }

    return (
      <div className='contact-form'>
        {contactForm}
      </div>
    );
  }
}

export default ContactForm;
```

　ここまで紹介した例ではメールアドレスのエラーメッセージの表示であったが、問い合わせ内容も同様の手順でエラーメッセージを表示させることができる。

```react:ContactForm.js
import React from 'react';

class ContactForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isSubmitted: false,
      email: '',
      hasEmailError: false,
      content:'',
      hasContentError:false,
      
    };
  }

  handleEmailChange(event) {
    const inputValue = event.target.value;
    const isEmpty = inputValue === '';
    this.setState({
      email: inputValue,
      hasEmailError: isEmpty,
    });
  }

  handleContentChange(event){
    const inputValue=event.target.value;
    const isEmpty=inputValue==='';
    this.setState({
      content:inputValue,
      hasContentError:isEmpty,
    });
  }

  handleSubmit() {
    this.setState({isSubmitted: true});
  }

  render() {
    let emailErrorText;
    if (this.state.hasEmailError) {
      emailErrorText = (
        <p className='contact-message-error'>
          メールアドレスを入力してください
        </p>
      );
    }
    
    let contentErrorText;
    
    if(this.state.hasContentError){
      contentErrorText=(
        <p className='contact-message-error'>
          お問い合わせ内容を入力してください
        </p>
        );
    }
    
    let contactForm;
    if (this.state.isSubmitted) {
      contactForm = (
        <div className='contact-submit-message'>
          送信完了
        </div>
      );
    } else {
      contactForm = (
        <form onSubmit={() => {this.handleSubmit()}} >
          <p>メールアドレス（必須）</p>
          <input
            value={this.state.email}
            onChange={(event) => {this.handleEmailChange(event)}}
          />
          {emailErrorText}
          <p>お問い合わせ内容（必須）</p>
          <textarea 
            value={this.state.content}
            onChange={(event)=>{this.handleContentChange(event)}}
          />
          {contentErrorText}
          
          
          <input
            type='submit'
            value='送信'
          />
        </form>
      );
    }
    
    return (
      <div className='contact-form'>
        {contactForm}
      </div>
    );
  }
}

export default ContactForm;
```