Help us understand the problem. What is going on with this article?

State を使った React コンポーネントを利用したアプリ開発(React基礎講座7)

More than 1 year has passed since last update.

はじめに

今回は、前回学んだStateを使ったReactコンポーネントを利用して、ちょっとしたアプリケーションを作りたいと思います。

シリーズ

本記事はReact基礎講座のための連載になっています。気になる方のために、前の章は以下です。

State を使った React コンポーネント(React基礎講座6) - Qiita

最初の記事は、以下です。

Reactを使ってJSXの内容をレンダリングする(create-react-app)(React基礎講座1) - Qiita

テストの出来栄えを判定するちょっとしたアプリケーション

今回作成する、ちょっとしたアプリケーションの内容を説明します。

例えば、学校の100満点のテストを受けた時に

  • 100だった場合
  • 80点以上だった場合
  • 50点以上だった場合
  • それ以下だった場合

に、viewが変わるような仕掛けを、State を使った React コンポーネントを利用して作成していきましょう。

Reactアプリを作成する際の採用構成ファイル

index.js
import React from "react";
import { render } from "react-dom";

render(<App />, document.getElementById("root"));

次に、React.Componentを作成していきましょう。

主に必要な記述は

  • extends
  • constructor
  • render

でしたね。では、クラス名はテストなので、examとして書いていきましょう。

今回はテストの点数をstateにしてください。名前はscore(初期値: 10)とでもしていきましょう。

すると、こんな感じにかけると思います。

index.js
import React from "react";
import { render } from "react-dom";

class Exam extends React.Component {
  constructor(props) {
    super(props);
    this.state = { score: 10 };
  }
  render() {
    return <h1>{this.state.score}</h1>;
  }
}

render(<Exam />, document.getElementById("root"));

viewには10とだけ、表示されたと思います。

では、次に、温度変化をコントロールするボタンを作っていきます。

主な手順は

  • +ボタンと-ボタンのjsxを作成してください
  • 上記のボタンから、stateを変更するようなメソッドをアロー関数で作成してください
    • メソッド名
      • 1+する方は onPlusBtnClick()
      • 1-する方は onMinusBtnClick()

以下が、正解(書き方はいくらでもありますが...)。

index.js
import React from "react";
import { render } from "react-dom";

class Exam extends React.Component {
  constructor(props) {
    super(props);
    this.state = { score: 10 };
  }

  render() {
    return (
      <div>
        <h1>{this.state.score}</h1>
        <button onClick={this.onPlusBtnClick}>+</button>
        <button onClick={this.onMinusBtnClick}>-</button>
      </div>
    );
  }

  onPlusBtnClick = () => {
    this.setState({ score: this.state.score + 1 });
  };
  onMinusBtnClick = () => {
    this.setState({ score: this.state.score - 1 });
  };
}

render(<Exam />, document.getElementById("root"));

こんな感じですね。

同じような要領で、+10、そして、-10になるようなJSXとメソッドも作って見ましょう。

以下が、正解(書き方はいくらでもありますが...)。

index.js
import React from "react";
import { render } from "react-dom";

class Exam extends React.Component {
  constructor(props) {
    super(props);
    this.state = { score: 10 };
  }

  render() {
    return (
      <div>
        <h1>{this.state.score}</h1>
        <button onClick={this.onPlusBtnClick}>+</button>
        <button onClick={this.onMinusBtnClick}>-</button>
        <button onClick={this.onPlusBtnTenClick}>+10</button>
        <button onClick={this.onMinusBtnTenClick}>-10</button>
      </div>
    );
  }

  onPlusBtnClick = () => {
    this.setState({ score: this.state.score + 1 });
  };
  onMinusBtnClick = () => {
    this.setState({ score: this.state.score - 1 });
  };
  onPlusBtnTenClick = () => {
    this.setState({ score: this.state.score + 10 });
  };
  onMinusBtnTenClick = () => {
    this.setState({ score: this.state.score - 10 });
  };
}

render(<Exam />, document.getElementById("root"));

こんな感じですね。

テストの出来栄えを判定する条件を追加する

学校の100満点のテストを受けた時に

  • 100だった場合: 天才
  • 80点以上だった場合: 秀才
  • それ以下だった場合: 伸び代あり!

という評価を点数に合わせて動的に表示が変わるように作成しましょう。

手順としては

  • 上の条件で文字列を返すようなメソッドをアロー関数で作成する
    • メソッド名は evaluationScore
  • そのメソッドを受け取るJSXをh1以下に用意する

以下が、正解(書き方はいくらでもありますが...)。

index.js
import React from "react";
import { render } from "react-dom";

class Exam extends React.Component {
  constructor(props) {
    super(props);
    this.state = { score: 10 };
  }

  render() {
    return (
      <div>
        <h1>{this.state.score}</h1>
        <p>評価:{this.evaluationScore(this.state.score)}</p>
        <button onClick={this.onPlusBtnClick}>+</button>
        <button onClick={this.onMinusBtnClick}>-</button>
        <button onClick={this.onPlusBtnTenClick}>+10</button>
        <button onClick={this.onMinusBtnTenClick}>-10</button>
      </div>
    );
  }

  onPlusBtnClick = () => {
    this.setState({ score: this.state.score + 1 });
  };
  onMinusBtnClick = () => {
    this.setState({ score: this.state.score - 1 });
  };
  onPlusBtnTenClick = () => {
    this.setState({ score: this.state.score + 10 });
  };
  onMinusBtnTenClick = () => {
    this.setState({ score: this.state.score - 10 });
  };

  evaluationScore = score => {
    if (score >= 100) {
      return "天才";
    } else if (score >= 80) {
      return "秀才";
    } else {
      return "伸び代あり!";
    }
  };
}

render(<Exam />, document.getElementById("root"));

こんな感じですね。

テストの出来栄えを判定してCSSのスタイリングも変化するように条件を追加する

今度は、state(テストの点数)の値に伴ってCSSが変化するような変更を加えていきましょう。

手順としては以下のような感じ

  • h1タグにclassName(Reactでスタイリングする場合の書き方)を指定して、関数evaluationScoreに引数this.state.scoreを渡して、そこから帰る文字列をクラス名として利用する
  • style.css にスタイルを書いて、index.jsでそれをimportする
  • cssとindex.jsは同じ階層
  • 関数(evaluationScore)が返す文字列も日本語から英語にします
index.js
import React from "react";
import { render } from "react-dom";
import "./style.css";

class Exam extends React.Component {
  constructor(props) {
    super(props);
    this.state = { score: 10 };
  }

  render() {
    return (
      <div>
        <h1 className={this.evaluationScore(this.state.score)}>
          {this.state.score}</h1>
        <p>評価:{this.evaluationScore(this.state.score)}</p>
        <button onClick={this.onPlusBtnClick}>+</button>
        <button onClick={this.onMinusBtnClick}>-</button>
        <button onClick={this.onPlusBtnTenClick}>+10</button>
        <button onClick={this.onMinusBtnTenClick}>-10</button>
      </div>
    );
  }

  onPlusBtnClick = () => {
    this.setState({ score: this.state.score + 1 });
  };
  onMinusBtnClick = () => {
    this.setState({ score: this.state.score - 1 });
  };
  onPlusBtnTenClick = () => {
    this.setState({ score: this.state.score + 10 });
  };
  onMinusBtnTenClick = () => {
    this.setState({ score: this.state.score - 10 });
  };

  evaluationScore = score => {
    if (score >= 100) {
      return "genius";
    } else if (score >= 80) {
      return "excellence";
    } else {
      return "potential";
    }
  };
}

render(<Exam />, document.getElementById("root"));
style.css
/* 青 */
.genius {
  color: #2f00ff;
}
/* 緑 */
.excellence {
  color: #00ff0d;
}
/* 赤 */
.potential {
  color: #ff0000;
}

0595284e09dae1e06e23e80653de890d.gif

こんな感じですね。

リファクタ

多少、冗長な書き方があるので、短く書いていきましょう。

{}で必要なものを取り出します。

例えば、この記述 this.state.score

const { score } = this.state

これは、stateの中に、scoreがあれば、constで定義したscoreに入れる。という意味です。こうかけば、いちいち this.state.score 書かなくても、score だけで済みます。

renderメソッドの中と、その下のsetStateする関数の中で const { score } = this.state;を書いています。

index.js
import React from "react";
import { render } from "react-dom";
import "./style.css";

class Exam extends React.Component {
  constructor(props) {
    super(props);
    this.state = { score: 10 };
  }

  render() {
    const { score } = this.state;
    return (
      <div>
        <h1 className={this.evaluationScore(score)}>
          {score}</h1>
        <p>評価:{this.evaluationScore(score)}</p>
        <button onClick={this.onPlusBtnClick}>+</button>
        <button onClick={this.onMinusBtnClick}>-</button>
        <button onClick={this.onPlusBtnTenClick}>+10</button>
        <button onClick={this.onMinusBtnTenClick}>-10</button>
      </div>
    );
  }

  onPlusBtnClick = () => {
    const { score } = this.state;
    this.setState({ score: score + 1 });
  };
  onMinusBtnClick = () => {
    const { score } = this.state;
    this.setState({ score: score - 1 });
  };
  onPlusBtnTenClick = () => {
    const { score } = this.state;
    this.setState({ score: score + 10 });
  };
  onMinusBtnTenClick = () => {
    const { score } = this.state;
    this.setState({ score: score - 10 });
  };

  evaluationScore = score => {
    if (score >= 100) {
      return "genius";
    } else if (score >= 80) {
      return "excellence";
    } else {
      return "potential";
    }
  };
}

render(<Exam />, document.getElementById("root"));

これで、冗長な書き方が多少なくなったかと思います。

以上です。参考にしてみてください。

参考

  • 改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで | 山田 祥寛
ryosuketter
偏差値50台 大学理系院卒、一部上場企業でWebエンジニア(3年目)半人前レベル。普通の34歳おっさんでも頑張ったら一人前のフロントエンドエンジニアになれるのか?の検証 Qiita です。
https://note.com/ryosuketter
life-a-tm
人生のイベントや日常生活に密着した比較サイト、情報サイト等様々なウェブサービスを企画・開発・運営
https://life.a-tm.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away