【React】これで基礎はばっちり基礎 総まとめ

React

.jsファイルの構成

import React from 'react';        Reactをimport
class App extends React.Component {    React.Componentを継承するクラスの定義
  render() {               JSXを戻り値とするrenderメソッドを定義
    const text = 'Hello';
    return (
      <div> { text } </div>
    );
  }
}
export default App;                    クラスをexport

  • return内をJSXで記述し、この部分がブラウザに表示される。
  • returnの外にはJavaScriptを記述することができる

JSX

Reactで、見た目を作るコードを書くファイル

HTMLの役割をするもの

JSXの特徴

render() {
  return (
    <div>
      <h1>heading</h1>
      <p>paragraph</p>
    </div>
  );
}

  • return内に複数の要素があるとエラーとなるため<div>で囲って1つの要素とする必要がある。

コメントの書き方

{/*コメント*/}

JavaScriptの場合(returnの外)
// コメント

imgタグの書き方

<img src='https://〜.jpg'/>

タグの終わりに/が必要

イベント

<button イベント名 = { () => { 処理 } }></button>

イベントの例
onClick
<button onClick = { () => { 処理 } }></button>

処理をconsole.logとする場合
<button onClick = { () => { console.log('ボタン') } }></button>

state

ユーザーの動きに合わせて変わる値

ボタンを押すとstateが変わり、表示が変更される。

constructor(props)
  super(props);
  this.state = { name: 'コーヒー' }
}
render() {
  console.log(this.state);
  return (

> { name: 'コーヒー' }

ここで定義したオブジェクト{ name: ‘コーヒー’ }が、stateの初期値となる。

constructorやsuperは定型文!

定義したstateはthis.stateで取得する。

上記はオブジェクトを出力する方法。

値を取得する場合は以下のように.nameとする。

constructor(props)
  super(props);
  this.state = { name: 'コーヒー' }
}
render() {
  return (
    <h1>朝は{this.state.name}から始まる</h1>
  );
}

指定されたプロパティに対応するstateの値を変更する

this.setState({プロパティ名: 変更する値})

ボタンクリックで名前の表示を変える

  constructor(props) {
    super(props);
    this.state = {name: 'にんじゃわんこ'};
  }
  
  render() {
    return (
    	<div>
    	  <h1>こんにちは、{this.state.name}さん!</h1>
        <button onClick={() => {this.setState({name:'ひつじ仙人'})}}>ひつじ仙人</button>
        <button onClick={() => {this.setState({name:'にんじゃわんこ'})}}>にんじゃわんこ</button>
      </div>
    );
  }

{name:’ひつじ仙人’}は切り替え表示する文字。

ひつじ仙人はビューに表示している文字

メソッド化

メソッドは以下のように定義することができる。

class クラス名 {
  constructor(){

  }
  メソッド名() {
    行いたい処理
  }
}

  constructor(props) {
    super(props);
    this.state = {name: 'にんじゃわんこ'};
  }
  
  handleClick(name) {
    this.setState({name: name});
  }
  render() {
    return (
        <button onClick={() => {this.setState({name:'ひつじ仙人'})}}>ひつじ仙人</button>
        <button onClick={() => {this.setState({name:'にんじゃわんこ'})}}>にんじゃわんこ</button>
    );
  }

handleClickというメソッドを作り、その中でsetStateのnameプロパティの値を変更する処理を行う。

handleClickメソッドを呼び出すときに引数nameに「ひつじ仙人」「にんじゃわんこ」を渡す。

メソッドhandleClick(name)でメソッド化しているため、引数が以下のように変更となる。

{this.setState({name: 'ひつじ仙人'})}

↓

{this.handleClick('ひつじ仙人')}

カウントアップ機能を作る

stateの定義、stateの表示

constructor(props) {
  super(props);
  this.state = {count: 0};
}

render() {
  return (
    <div>
      <h1>
        {this.state.count}
      </h1>
      <button>+</button>
    </div>
  );
}

stateの変更

ボタンをクリックしたときに呼び出されるメソッドを定義する。

handleClick() {
  this.setState({count: this.state.count + 1});
}

render() {
  return (
    <div>
      <h1>
        {this.state.count}
      </h1>
      <button onClick={()=>{this.handleClick()}}>+</button>
    </div>
  );
}

Reactの表示の仕組み

Reactのコードを実際にブラウザに表示するには、App.js以外にもindex.jsとindex.htmlというファイルが必要になる。

App.jsのJSXのHTMLへの変換の仕方

index.js内で「ReactDOM.render(<App />, …」と書く

「…, document.getElementById(‘id名’));」と書く

これによりHTMLに変換される。

import React from 'react';

class App extends React.Component {
  render() {
    return (
      <div>
        <h1>Hello World</h1>
        <p>一緒にReactを学びましょう!</p>
      </div>
    );
  }
}

export default App;
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App';
ReactDOM.render(<App />, document.getElementById('root'));
<!DOCTYPE html>
<html>
  <head>
    <title>React App</title>
  </head>
  <body>
    <div id="root"></div>
    
    <script src="bundle.js"></script>
  </body>
</html>

CSSの読み込み

index.html内でstylesheet.cssを読み込む

<!DOCTYPE html>
<html>
  <head>
    <link rel="stylesheet" href="stylesheet.css">
    <title>React App</title>
  </head>

タグのCSSの書き方
class App extends React.Component {
  render() {
    return (
      <div>
        <h1>Hello World</h1>
        <p>一緒にReactを学びましょう!</p>
      </div>
    );
  }
}

h1 {
  color: red;
}
p {
  color: blue;
}

クラスのCSSの書き方
class App extends React.Component {
  render() {
    return (
      <div>
        <h1 className='title'>Hello World</h1>
        <p className='text'>Hello React</p>
      </div>
    );
  }
}

classじゃなくて、className

.title {
  color: red;
}
.text {
  color: blue;
}

コンポーネントについて

Reactでは見た目を機能毎にコンポーネント化している。

import React from 'react';
class Language extends React.Component {
  render() {
    return (
      JSX
    );
  }
}

コードの説明

①Reactをインポート

②React.Componentを継承するクラスを定義

③renderメソッドを定義 JSXを戻り値とする

これがコンポーネント作成の雛形!

Languageコンポーネントのブラウザでの表示の流れ

Language.js → App.js → index.js → index.html

App.jsでLanguageコンポーネントを呼び出さないといけない。

以下のようにLanguage.js内でexportする。

import React from 'react';
class Language extends React.Component {
  render() {
    return (
      JSX
    );
  }
}
export default Language;

App.jsの方では、以下を記述する。

  • Languageコンポーネントのインポート
  • JSX内に<コンポーネント/>を記述
import React from 'react';
import Language from './Language';

class App extends React.Component {
  render() {
    return (
      <div>
        <h1>Hello World</h1>
        <Language/>
      </div>
    );
  }
}

上記の<Language/>の数だけコンポーネントを呼び出せる。=表示できる。

<Language/>を複数回記述すると同じコンポーネントができる。

これらコンポーネントのHTML、CSSを変更する方法について見ていく。

App.jsからLanguage.js(コンポーネント)にデータを渡す。

class App extends React.Component {
  render() {
    return (
      <div>
        <Language
          name = '名前'
          image = '画像'
        />
      </div>
    );
  }
}

name, imageをpropsと言う。

「props名=値」で、propsを渡せる。

propsの受け取り

this.propsで受け取りができる。

class Language extends React.Component {
  render() {
    console.log( this.props );
    return (
      JSX
    );
  }
}

> 
{
  name: "名前"
  image: "画像"
}

propsの値の取得

{this.props.name}

画像の場合
<img src={this.props.image} />

上記のように、propsを使うことで、1つのコンポーネントに複数の値を入れることができる。

しかし、それらを一つずつ取得するのは大変。

そこでmapメソッドを使用する。

mapメソッド使用前

class App extends React.Component {
  render() {
    return (
      <div>
        <h1>言語一覧</h1>
        <div className='language'>
          <Language 
            name='HTML & CSS'
            image='https://~'
          />
          <Language 
            name='JavaScript'
            image='https://~'
          />
          <Language 
            name='React'
            image='https://~'
          />
        </div>
      </div>
    );
  }
}

mapメソッドを使用すると、以下のように書き換えられる。

class App extends React.Component {
  render() {
    const languageList = [
      {
        name: 'HTML & CSS',
        image: 'https://~'
      },
      {
        name: 'JavaScript',
        image: 'https://~'
      },
      {
        name: 'React',
        image: 'https://~'
      }
    ];

    return (
      <div>
        <h1>言語一覧</h1>
        <div className='language'>
          {languageList.map((languageItem) => {
            return (
              <Language
                name={languageItem.name}
                image={languageItem.image}
              />
            )
          })}  
        </div>
      </div>
    );
  }
}

languageListという配列を作成し、mapメソッドを用いて1つずつオブジェクトを取り出し、Languageコンポーネントを呼び出し、その中でpropsを渡す。

propsを渡すとは、LanguageItem→languageItem.nameやlanguageItem.imageに渡すこと。

モーダル

モーダルの作成手順

  1. コンポーネントの中にモーダルのJSXを追加する
  2. 初期状態でモーダルを隠す
  3. モーダルの表示・非表示

モーダルが表示されているかそうでないかをstateを使って判定する。

constructorを定義し、stateを定義する。

そして、stateのプロパティ名にisModalOpenを定義し、初期値をfalseとする。

class Lesson extends React.Component {
  constructor(props) {
    super(props);
    this.state = {isModalOpen:false}
  };

この時点ではモーダルは表示され続けている。

そのためisModalOpenがtrueのときだけモーダルが表示されるというようにする。

① 変数modalを定義

② stateのModalがtrueのとき、変数modalに、モーダルのJSXを代入する

③ return内で、モーダルJSXを変数modalに書き換える

  render() {
    let modal;
   
    if (this.state.isModalOpen){
      modal = (
        <div className='modal'>
          <div className='modal-inner'>
            <div className='modal-header'></div>
            <div className='modal-introduction'>
              <h2>{this.props.name}</h2>
              <p>{this.props.introduction}</p>
            </div>
            <button className='modal-close-btn'>
              とじる
            </button>
          </div>
        </div>
      );
    }
    return (
      <div className='lesson-card'>
        <div className='lesson-item'>
          <p>{this.props.name}</p>
          <img src={this.props.image} />
        </div>
        {modal}
      </div>
    );
  }

これで、初期状態でモーダルが隠れるようになった。

次は、クリック時にモーダルが表示されるようにする。

① stateを変更するhandleClickLessonメソッドを定義する。

② そして、isModalOpenの値をtrueにする処理をする

③rerurn内にonClickイベントを追加し、 クリック時にhandleClickLessonを呼び出されるようにする。

class Lesson extends React.Component {
  constructor(props) {
    super(props);
    this.state = {isModalOpen: false};
  }
  
  handleClickLesson () {
    this.setState({isModalOpen:true});
  }
  
  render() {
    let modal;
    if (this.state.isModalOpen) {
      modal = (
        <div className='modal'>
          <div className='modal-inner'>
            <div className='modal-header'></div>
            <div className='modal-introduction'>
              <h2>{this.props.name}</h2>
              <p>{this.props.introduction}</p>
            </div>
            <button className='modal-close-btn'>
              とじる
            </button>
          </div>
        </div>
      );
    }
    return (
      <div className='lesson-card'>
        <div
          className='lesson-item'
          onClick={() => {this.handleClickLesson()}}
        >
          <p>{this.props.name}</p>
          <img src={this.props.image} />
        </div>
        {modal}
      </div>
    );
  }
}

あとは、モーダルを「とじる」ボタンで閉じれるようにするだけ!

上記のモーダル表示のクリックイベントと同様に、「とじる」のクリックイベントを作成する。

class Lesson extends React.Component {
  constructor(props) {
    super(props);
    this.state = {isModalOpen: false};
  }

  handleClickLesson() {
    this.setState({isModalOpen: true});
  }
  
  handleClickClose () {
    this.setState({isModalOpen:false});
  }

  render() {
    let modal;
    if (this.state.isModalOpen) {
      modal = (
        <div className='modal'>
          <div className='modal-inner'>
            <div className='modal-header'></div>
            <div className='modal-introduction'>
              <h2>{this.props.name}</h2>
              <p>{this.props.introduction}</p>
            </div>
            <button
              className='modal-close-btn'
              onClick={() => {this.handleClickClose()}}
            >
              とじる
            </button>
          </div>
        </div>
      );
    }

    return (
      <div className='lesson-card'>
        <div
          className='lesson-item'
          onClick={() => {this.handleClickLesson()}}
        >
          <p>{this.props.name}</p>
          <img src={this.props.image} />
        </div>
        {modal}
      </div>
    );
  }
}

お問い合わせフォームの作成

見た目(JSX)の作成

class ContactForm extends React.Component {
  render() {
    return (
      <div className='contact-form'>
        <form>
          <p>メールアドレス(必須)</p>
          <input />
          
          <p>お問い合わせ内容(必須)</p>
          <textarea />
          
          <input 
            type = 'submit'
            value = '送信'
          />
        </form>
      </div>
    );
  }
}

送信完了時に表示するメッセージを準備する

stateでフォームが送信されたかどうかを管理する。

送信されていなければstateはfalseとする。

そのため、初期値はfalseに設定する。

空の変数contactFormを定義し、isSubmittedで条件分岐

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

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

メッセージを表示する

送信されたら表示が切り替わるようにする。



<form onSubmit={() => {処理}}>

</form>

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

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

handleSubmitメソッドを定義して、

フォーム送信時に handleSubmitメソッド が実行されるようにonSubmitイベントを追加する。

stateでフォームに入力された値を管理する

①stateにemailの項目を追加する。

②input タグにstateのemailを指定して表示する。

  constructor(props) {
    super(props);
    this.state = {
      isSubmitted: false,
      email:'mail@prog-8.com'
    };
  }

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

  render() {
    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} />
          <p>お問い合わせ内容(必須)</p>
          <textarea />
          <input
            type='submit'
            value='送信'
          />
        </form>
      );
    }

onChangeイベントを追加して、入力値を取得し、コンソールに出力する。

          <input
            value={this.state.email}
            onChange={(event) => {console.log(event.target.value)}}
          />

handleEmailChangeという名前のメソッドを定義して、

入力値eventを代入する定数inputValueを定義し、

stateのemailを更新する。

inputタグのonChangeイベントにhandleEmailChangeメソッドの引数eventに値を渡す。


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

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

  render() {
    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)}}
          />
          <p>お問い合わせ内容(必須)</p>
          <textarea />
          <input
            type='submit'
            value='送信'
          />
        </form>
      );
    }

フォーム入力エラーメッセージを表示する

hasEmailErrorというstateを初期値falseで定義する。

emailErrorTextを定義し、

hasEmailErrorの値によってエラーメッセージの表示・非表示を切り替える条件式を設定

  constructor(props) {
    super(props);
    this.state = {
      isSubmitted: false,
      email: '',
      hasEmailError: false
    };
  }

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

  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>
      );
    }

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

  handleEmailChange(event) {
    const inputValue = event.target.value;
    /* 定数isEmptyを定義し、入力チェックの結果を代入 */
    const isEmpty = inputValue === ''
    
    /* setStateを使ってemailとhasEmailErrorを一緒に更新 */
    this.setState({
      email: inputValue,
      hasEmailError: isEmpty
    });
    
  }

コメント

タイトルとURLをコピーしました