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

React.jsでボタンをおしたら何かを表示するやつを試行錯誤しながらサンプルに追加するチュートリアル

More than 1 year has passed since last update.

なぜ?

React.js の説明ページはいろいろあるので、もう今更書くことなんてないのですが。

業務で急にReactの保守をやるはめになった人って、すでにReactのコードがある状態で「ボタンおしたらxxになるの作って」とか言われると思うのです。

そんな時に、馬鹿正直にチュートリアルで最初からReactを勉強するのも大事ですが(時間があればそれが一番ですが…)、なるべくやりたいことに早く着地するため、すでにあるサンプルをちょっとずついじりながら学ぶのもいいかな、と、おもってまとめてみました。

前提

Node.jsはインストールしておいてください。

最初にサンプルコードがあったことにするための準備

サンプル用にディレクトリを作る。

$ mkdir sample
$ cd sample

Reactのサンプルを作る。

$ npm install -g create-react-app
$ create-react-app hello

こうすることで、hello というディレクトリができてそこにサンプルが作成されます。
そこそこ時間がかかりますが、おわったら次に進みます。

$ cd hello
$ npm start

これでローカルにサーバが立ち上がります。
http://localhost:3000/ にアクセスしてみましょう。ちゃんと表示されましたね?

ここまでは準備で次からが本番です!

ボタンをつけていじってみる

例えば今回はこんな例題で考えてみます。

今の画面に、新規で「天気を表示」ボタンを付けて、おしたら天気がでるようにしてほしい

さて。

ボタンをつける...

まずはボタンをつけてみましょう。えっと。。。どこに?
現在のディレクトリ構成はこんな感じです。

hello/
  +- node_modules/
  +- public/
  |    +- favicon.ico
  |    +- index.html
  |    +- manifest.json
  +- src/
  |    +- App.css
  |         :

「まあ、HTMLかな?」 と思って、index.html を見てみると……

public/index.html
<!DOCTYPE html>
<html lang="en">
  <head>
        :
    <title>React App</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
  </body>
</html>

実質HTMLなにも書いてませんね。

React.jsはそういうものなのです。
じゃあ、JavaScriptで何かやってるんだろう。

「それっぽいjsは……」 と思って、App.js を見てみると……

src/App.js
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

class App extends Component {
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <p>
            Edit <code>src/App.js</code> and save to reload.
          </p>
          <a
            className="App-link"
            href="https://reactjs.org"
            target="_blank"
            rel="noopener noreferrer"
          >
            Learn React
          </a>
        </header>
      </div>
    );
  }
}

export default App;

うん、これっぽい。あたりです。
ということでボタンを追加してみます。

src/App.js
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

class App extends Component {
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <p>
            Edit <code>src/App.js</code> and save to reload.
          </p>
          <a
            className="App-link"
            href="https://reactjs.org"
            target="_blank"
            rel="noopener noreferrer"
          >
            Learn React
          </a>
          {/* ****** ここから追加 ****** */}
          <a class="my-tenki-button" href="#">天気を表示</a>
          {/* ****** ここまで追加 ****** */}
        </header>
      </div>
    );
  }
}

export default App;

このファイルは React.js で言うとことのコンポーネントと呼ばれるもので、JSXという、JavaScriptのようなHTMLのようなもので書かれています(JavaScriptなのですけど……)
なので、HTMLも普通のHTMLと微妙に違っています。わかりやすいところだとコメントが <!-- --> ではなく {/* */} とかだったりします。この辺りはちゃんと公式マニュアルを見るのがよいですが、書いてみるとどこかでエラーがでますので、エラーが出てから調べても良いと思います。

ついでに見た目を少し整えるためにcssもいじっておきます。
それっぽいCSSの最後に追加しておきます。

src/App.css
    :

.my-tenki-button {
  color: #fff;
  border: 1px solid #fff;
}

App.jsの先頭あたりをみるとimport './App.css';とあるので迷わずcssは見つけられると思います!

この状態で画面はこんな感じになります。
無事にボタンがつきました。

image.png

さて、次はクリックイベントです。クリックしてなにか動かす処理です。

クリックして何か動かす処理なのでもちろん js で書くことになりそうです。
ということで App.js を書き換えます。

具体的には、クリック時に呼び出される関数を追加して、クリック時(onClick)でその関数が呼び出されるように書き加えます。

src/App.js
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

class App extends Component {
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <p>
            Edit <code>src/App.js</code> and save to reload.
          </p>
          <a
            className="App-link"
            href="https://reactjs.org"
            target="_blank"
            rel="noopener noreferrer"
          >
            Learn React
          </a>
          {/* ****** ここから onClick を追加 ****** */}
          <a onClick={this.handleClick}>天気を表示</a>
          {/* ****** ここまで追加 ****** */}
        </header>
      </div>
    );
  }
  // ***** クリック時呼び出される関数を追加 *****
  handleClick() {
    alert('Click!!')
  }
  // ***** ここまで追加 *****
}

export default App;

コメントで囲んだ部分だけが更新されたところですが、念のため全コードのせておきます。

ここで実際にブラウザでクリックをしてみると、アラートのポップアップが出たと思います。

さて、次は、実際に外部から情報をとってきてそれでページを更新してみます。

ぱっと考えれば jQuery とかでやりたくなりますが…… まあ、Reactやってるんだから、Reactっぽくやりましょう 笑

まずは、天気を表示するためのdivとかを用意します。

これは普通にHTMLで<div>とか入れておけばOKです。
その <div> 内には、Reactのコンポーネント内で扱う変数 this.state.tenki を表示するように書いておきます。
Reactっぽく {} で変数を囲んで {this.state.tenki} を埋め込みます。
this.state.tenki はコンストラクタ内で初期値を定義し、クリック時に呼び出される handleClick で値が書き換わるようにしておきました。
値を書き換えるとHTMLの表示も勝手に書き換わるのです。すごい。

ちょっと一気に変えましたが、下記が現在のコードです。
(前回説明用のコメントは削除して、今回追加部分だけコメントいれてます)

src/App.js
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

class App extends Component {
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <p>
            Edit <code>src/App.js</code> and save to reload.
          </p>
          <a
            className="App-link"
            href="https://reactjs.org"
            target="_blank"
            rel="noopener noreferrer"
          >
            Learn React
          </a>
          <a onClick={this.handleClick}>天気を表示</a>

          {/* ****** ここに天気をだす ****** */}
          <p>{this.state.tenki}</p>
          {/* ****** ここまで追加 ****** */}

        </header>
      </div>
    );
  }
  handleClick() {
    // ***** tenkiの値の書き換え *****
    this.setState({tenki:"晴れ(仮)"});
  }

  // ***** コンストラクタ追加して初期値の設定 *****
  constructor(props) {
    super(props);
    this.state = { tenki : "まだ天気とってません" };
    this.handleClick = this.handleClick.bind(this);
  }
  // ***** ここまで追加 *****
}

export default App;

これで、クリックすると まだ天気をとってません晴れ(仮) になります。

コンストラクタの this.handleClick = this.handleClick.bind(this); だけ少し特殊な事情があります。これはES6のextendsでthisがbindされないという仕様のためいれているものです。ひょっとしたらこのひな形の作成とかで今後かわるかもしれませんが、2019年1月時点ではこの書き方で動きます。

さて、次こそは、外部APIを呼び出します!!

最近のJavaScriptにはfetchという便利な機能が用意されているので、それを使っていきます。
fetchによって外部のAPIを呼び出し結果が取得できるので、その結果をパースして、先ほどと同じように this.setStatus() で値を書き換えることなります。

コード見た方がはやいと思うのでこちらです。

src/App.js
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

class App extends Component {
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <p>
            Edit <code>src/App.js</code> and save to reload.
          </p>
          <a
            className="App-link"
            href="https://reactjs.org"
            target="_blank"
            rel="noopener noreferrer"
          >
            Learn React
          </a>
          <a onClick={this.handleClick}>天気を表示</a>

          <p>{this.state.tenki}</p>

        </header>
      </div>
    );
  }
  handleClick() {
    // ***** tenki API から天気をしゅとくして書き換え *****
    // ***** しようと思ったけど良い天気APIがなかったから、郵便番号から住所検索のAPIにしちゃった てへ
    fetch('https://api.zipaddress.net/?zipcode=1000005', {
      mode: 'cors'
    })
    .then(res => {
      return res.json();
    })
    .then(json => {
      this.setState({tenki:json.data.fullAddress});
    })
    // ***** ここまで書き換え *****
  }

  constructor(props) {
    super(props);
    this.state = { tenki : "まだ天気とってません" };
    this.handleClick = this.handleClick.bind(this);
  }
}

export default App;

!謝罪!
コード中のコメントにも書きましたが、天気をさくっととれる良いAPIが見つからなかったので「郵便番号から住所を検索する」APIを呼び出しました!!! なので天気ではなく、住所がでます。。。 まあ、REST API呼び出して、jsonにして、画面を更新する、という主旨は伝わったともうのでよしとしてください。

今回追加分でいうと、fetcでAPIを読んで結果をjsonにしてthis.setStateする、というのを、クリック時に呼び出されるhandleClickで行う、というシンプルな構造です。

これで実際に画面上でクリックしてみると・・・・・・

image.png

天気を表示といいながら、住所がでますが、そこはご愛敬ですが、とりあえずやりたいことはやれたのでよしとします。

補足

ほとんどまったくReact.jsとは何か? JSXとは何か? stateとは? みたいなところをすっ飛ばして説明しました。

けれどReact.jsのような膨大なフレームワークを最初からそうやって調べていくと終わりが見えないので、とりあえずこの記事くらい動かしてみて、あとは動かしながら気になるところを調べていく方が効率的かなと思います。

ということで、インターンとかで会社に入って急に「React.jsやって!」と無茶ぶりされた若手が泣かないように、わたしがReact.jsやるならこの辺りから勉強をスタートするかなー、という観点でまとめてみました。

少しでもお役に立てたなら いいね でも押してくれると嬉しいです m__m

567000
組み込みからWebサービスから機械学習からオブジェクト指向から開発プロセスから認定ScrumMasterからなんならUI/UX/HCD/デザイン思考まで。 投稿した内容でなにかあったらTwitterなどへ気軽にどうぞです。
https://twitter.com/aka567000
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