ふんばりフロントエンジニアのブログ

新米フロントエンジニアの備忘録です。ふんばり温泉タオル欲しい...

タブレット・スマホのデザインに768pxが多い理由とは

久しぶりの投稿ですね…

わりと沖縄へ行ったり熱海へ行ったりと最近は忙しめでした(笑)

さて、今回はデザインファイルを触るときによく見かける「768px」という数値についてお話しようと思います。

正直「半端やな…770pxでもええやんけ…」とずっと思っていたのですが最近お話を聞いて納得したので備忘録的に残しておこうと思います。

なぜ768pxがデザインの幅として多いのか?

この理由は意外と単純明快なものでした。

結論から言うと「768px」がタブレット最小幅だからです。

「え、それより幅が狭いタブレットあるくない?」と思いますが、実は基準としているのは「iOS製品」なんです。

f:id:ma1129nm:20180927173001j:plain

こちらはSafariで「レスポンシブデザインモード」にしたときの画面ですが、たしかに一番タブレットで小さいのは「iPad mini」でその画面幅は「768px」となっています。

そして、逆に一番大きいサイズは「iPad Pro」で「1024px」ですね。

「なるほど」とここで合点がいったのですが、わりとCSSでブレイクポイントを指定する際に「1024px」までをタブレットデザインとする表記が多いのはこういうことかと…

つまり1024px以上のタブレットが現在提供されていないので、それ以上は「PCデザインでいいっしょ!」ということですね。

少し話がそれましたが、タブレットスマホデザインとして768pxが多いのはこのような単純な理由からのようです。

でもたまに「828px」のタブレットスマホデザインも見かけますよね。

これはどういうことなのでしょうか?

デザイン幅が828pxはの理由は?

デザイン幅が828pxである場合も、やはりiOS製品に関係があるよう。

そしてこちらの数値はタブレットデザインというより、スマホデザインに比較的見られる数値かもしれませんね。

先ほどのレスポンシブデザインモードをまた見てみてください。

スマホで一番大きい画面幅の機種はどれですか?

そう、「iPhone 8 Plus」ですよね。

そしてこの幅は「414px」となっています。

ここで忘れてはいけないのが「Retina ディスプレイ」でしょう。

 

Retinaディスプレイって?~

Retinaディスプレイは「高精細」なディスプレイです。

このRetinaディスプレイがなぜ高精細なのかと言うと、「ppipixel per inch)」というディスプレイの解像度を示す単位が大きいためです。

このppi1インチにどれだけピクセルが入るか、という単位。

つまりこの数値が大きいほど1インチ当たりのピクセル数が多くなるので高精細になる、というわけですね。

Retinaディスプレイが搭載されたのはiPhone4からですが、このiPhone4が発売されるより前のApple製品のppiは「100~200ppi」ほどでした。

しかし、Retinaディスプレイを搭載したiPhone4のppiは「326ppi」。

そして先ほどのiPhone8Plusでは「401ppi」となっています。

つまり従来の解像度の二倍の解像度になっているんですね。

これがRetinaディスプレイが高精細なディスプレイたる理由です。

 

さて、Retinaディスプレイに関する話をしてみましたが従来の製品より解像度が二倍になっていることが分かりました。

つまり?

そうなんです、デザインを作る際には「Retinaディスプレイに対応するために二倍のデザイン幅でデザインを作らないとRetinaディスプレイに対応する解像度にならない」んです。

そして、現在提供されているiPhoneで一番大きい画面幅なのが「iPhone8 Plus」の「414px」、そしてその二倍の数値が「828px」なのでスマホデザインにおいては「828px」のデザインが多くなっているのでしょう。

スマホタブレットデザインのデザイン幅に関してはこれくらいですかね…

PCのデザイン幅は基準とするものが結構難しいようですが、一般的には「1280px」が多いようです。

しかし、画面幅いっぱいのコンテンツがデザインにあった場合、どのあたりで画面幅いっぱいのコンテンツをやめるか、対処するかを決めておかないととんでもないことになってしまうので気を付ける必要がありますね。

最近デザインを作ったりもしているので、今回聞いたお話はかなり貴重でした…

もしかしたら知っている方が多い話だったかもしれませんが、私にとってはインパクトが強かったので書いてみました。

今度はデザインの話ができればいいな…頑張ります~~

【Atom】atom-beautifyでPHPが整形できない…設定を変更しよう!

今回は私が愛用しているエディター「Atom」についての備忘録です。

今回の問題はAtomのコード整形パッケージ「atom-beautify」でPHPの整形がうまく行かない、ということについて。

エラーが出るわけではないのですが、注意書きで次のようなポップアップが出てきます。
f:id:ma1129nm:20180907153911p:plain
何やら内容としては、「PHP_CS_Fixerのパス設定が非推奨になってるので、変えてください」ということのよう。
PHP_CS_FixerはPHPのコードを整形するためのツールで、こちらはatom-beautifyを利用する際に確かダウンロードしてきたような気が…
まあ何はともあれ、このツールを使ってatom-beatuifyは整形をかけるのでもちろん正しくパスが通っていないと整形してくれないわけです。
ということでatom-beautifyのsettingsを見てみると、確かにPHPのところの「PHP-CS-Fixer Path」にパスが記載されています。
ただ、この「PHP-CS-Fixer Path」でパスを指定する方法がもうダメみたいですね。
そのため、まずはここにパスを記載している方は消しちゃってください。
そして新しく推奨されているのがatom-beautifyのsettings配下にある「Executables」内の「PHP」と「PHP_Fixer」にパスを通す、というもの。
PHPには「PHPのバイナリファイルがあるところまでの絶対パス」、「PHP_Fixer」は「ダウンロードしたphp-cs-fixer.pharがあるところまでの絶対パス」を書いてあげます。
f:id:ma1129nm:20180907155049p:plain
これでもう一度atom-beautifyを「opt+Ctrl+B」で実行するとできるようになるはずです。
ちなみに、phpファイルの中に記載されているHTMLは整形してくれないみたいですね...残念...

Dockerコンテナ内でComposerコマンドを使えるようにするメモ

Dockerのコンテナ内でComposerを使おうとした時のメモです。

まず、何も考えずに「curl -sS https://getcomposer.org/installer | php」でComposerをインストールするとカレントディレクトリにcomposer.pharが置かれます。

もちろんこのままではcomposerコマンドが利用できません。

Composerコマンドを使えるようにするには「/usr/local/bin」配下にcomposer.pharを配置しなければならないのですが、ただ置いただけではComoserコマンドを利用することはできません。

そこで行うのが「/usr/local/bin」配下に置いた「composer.phar」のリネームです。

「mv composer.phar composer」として「composer」にリネームすることで、Composerコマンドが利用できるようになりました!

他にも「/usr/local/bin」配下にcomposerディレクトリを作る、という方法もあるらしいですが私はそれで対処できませんでした...

とりあえず、一番手っ取り早いのは

  1. 「/usr/local/bin」に移動
  2. curl -sS https://getcomposer.org/installer | php」を打つ
  3. 「mv composer.phar composer」でリネーム

という感じでしょうか。

上手くいかなかったら教えてください〜

JavaScriptでアプリを作る!React Nativeの環境を作ってみよう

「ちょっとReactでアプリ作れるっぽいんだけど触ってみてくんない?」というお言葉から、本日はReact Nativeをかるーく触ってみました!
以前Reactを触ってみたお話しをしましたが、React Nativeはアプリケーションを作るためのものという認識なので触れてなかったんですね...
hubarifront.hatenablog.com
ただ、やはり触ってみた所感としては「ReactはReactだ!」、そして「SwiftやJavaなどを使って本格的にアプリを作るのはちょっと億劫だなあ」というフロントエンジニアの方にはもってこいのフレームワークだなあと改めて実感したところであります。
ということで、今回はReact Nativeをかるーく触ったお話をしていきたいと思います!

React Nativeの環境を作る!

React Nativeの環境はどうやらReactとは少し違うよう。
なんせアプリ開発ですからね...
公式ドキュメントを見る限り大雑把に分けると二つの方法にわかれます。

1. 「npm install -g create-react-native-app」で一発
2. nodeとwatchmanをbrew install、react-native-cliをnpm installしてprojectをinitする方法

まあReactの環境構築と似たような感じですね。
前回Reactでプロジェクトを作成したときは2の方法をとって、一から作っていたので今回は1の提供されているデフォルトのプロジェクトをインストールする方法をとりました。
本来ならつまづくところではないのですが、わたくしここでつまづきました....
というのも最近Macの様子がおかしく、時々Homebrewの挙動がやばいんですよね(笑)
まず、「npm install -g create-react-native-app」は問題なく入りました。
次に、「create-react-native-app プロジェクト名」でプロジェクトを作るのですが、ここも問題なかったです。
この二点を実行することでReact Nativeを動かす要素は揃ったはずだったのですが、「npm start」をすると「watchmanを入れるように」というエラーが。
ここで「brew install watchman」を打ったのですが、20分待っても終わらない...
結局何回やってもダメだったので、「OSを更新したからHomebrewの調子が悪いんかな?」ということでHomebrewのアンインストールをすることに。
そして再インストールをすることになったのですが、今度はHomebrewのインストールで止まる...

もう弾けそうでしたね、逆に。

何度か「usr/local」配下に作られているhomebrewやCellarなどを除去してはインストール、ということを繰り返していましたが結局解決はできず。
そこで試したのが「セーフブート」です。
セーフブートはmacの起動時のオプションでキャッシュクリアなどをして最低限の状態で起動してくれるモード。
セーフブートで起動してからさらに再起動するとキャッシュクリアして綺麗な状態で起動することができるんですね。
早速これを行いまたインストールしたところ、Homebrewもwatchmanも問題なくインストールされました...
おそらくキャッシュに残っているところをインストール時に見に行ってたんですかね??
細かいことはわかりませんが、とりあえずセーフブートからの再起動で正常にHomebrewが正常に戻り、Watchmanもインストールができました。
あとはもうこっちのもんです。
先ほどの「create-react-native-app プロジェクト名」で作ったプロジェクトにcdして「npm start」を打つだけ!
そうすると、「starting packager...」という文言が出て、最終的にはそこにQRコードが表示されます。
このQRコードを読むことで、シミュレーターを表示できるのですがここで必要になってくるのが「expo」というアプリ。
これはiOSでもAndroidでもダウンロードできるアプリなので、個人的にはexpoを使って実機で確認するのが一番いいのかなーとか思ったりしますね。
もちろん「npm run ios」をするとXcodeのシミュレーターが立ち上がったりしますが、結局はexpoに行くので...
ということで、開発環境はexpoを使った方法がおすすめです!

ふう...
本当はコードについてもお話しようと思ったのですが、ちょっと酔いが回ってしまったのでまた今度の機会にさせてもらおうと思います...
今回の内容でとりあえずReactNativeを動かすことはできるのでぜひお試しあれ!

Seleniumでブラウザテストを自動化!Javaでブラウザを動かそう!

今回はブラウザテストについてお話ししようと思います。

以前記事で書いた「診断コンテンツ」がありましたが、結局これはReactを使ってもっとボリュームのあるものを現在開発しています。

hubarifront.hatenablog.com

ただ、診断コンテンツのように選択肢によって結果が変わるものには「テスト」が必要。

しかし、今回開発しているのは「2つの選択肢がある設問が9個」で選んだ選択肢によって結果が分かれる、というもの。

つまり単純に考えると「2の9乗=512通り」のパターンがあることになります。

「こりゃあえらいこっちゃ…」

512通りを全て確認するのはかなり大変ですよね。

現在完璧に全部をテストできる状態にはなっていないのですが、Seleniumを使ってブラウザテストを初めてやってみたので備忘録として残しておきたいと思います。

Seleniumとはなんぞ???

Seleniumとは、UIテストツール、というかブラウザで表示されている要素を直接触れることなくスクリプトで操作できるツールです。

RubyPythonなど様々な言語で利用できるものですが今回は昔少しだけ触ったことのあるJavaを使ってみました。

では早速ですが、Seleniumで操作することのできる簡単な例をご紹介したいと思います。

        String url = "";
        String type = "";
        try {
            url = "https://www.yahoo.co.jp/";
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        WebDriver driver = new ChromeDriver();
        driver.get(url);

こちらを動かすと、自動的にGoogleChromeで「yahoo」のHPが表示されます。 こちらのコードは簡単ですが、基本となるものなのでしっかり抑えておきましょう。 まず重要になるのは「WebDriver」です。 WebDriverはなんとなくのイメージとしてブラウザに繋げるためのオブジェクトと捉えていただければ大丈夫かと思います。 そしてこのWebDriverという型でブラウザのdrverをnewしてインスタンスを作るわけなのですが、このインスタンス化によってどのブラウザを使うか、ということを選ぶことができます。 今回使用したのは「GoogleChrome」なので「ChromeDriver」をnewしてdriverインスタンスを作っています。 このインスタンス化をすることによってWebDriverがもつメソッドを利用することができるんですね。 上の例で使っているメソッドは「get(URL)」というメソッドで、これは引数のURLを開くメソッドです。 そのため、上の例ではyahooのURLが入っているのでこれを実行するとyahooのHPが表示される、というわけです。 このようなメソッドは他にもあり、WebDriverインスタンスを作ることで表示されている要素を検索して取ってきたり、要素をクリックできるようになったりします 。 さて、今回やりたいことは「512通り」ある選択肢を漏れなくテストしたい、というもの。 テスト内容としては、結果ページで出た「タイプ名」と、条件とした選択肢通りにクリックしてそのタイプになるかを確認したい。 となると、まずは2の9乗のパターンを全部吐き出すような処理を書かなければいけません。 ここで、今回行うテストの想定は - 1か0で判断してどちらの選択肢をクリックするかを決める - 2の9乗なので、「512」になるまで2進数で9桁の文字列を配列で作る というようなことを考えました。 開発している診断コンテンツは「右」か「左」のどっちを押すか、というようなものですので0か1で判断することはもちろん可能です。 では512通りの選択肢を試すためには何が必要か、と考えた時に2進数で512になるまで一つ一つの数字を2進数で表す、という考えに至りました。 先に512 までの2進数を表示するためのメソッドを載せておきます。

 public  String arrayCreate(int index) {
        List<String> decimal_array = new ArrayList<>();
//            二進数の配列を作成
        for (int i = 0; i < 30; i++) {
            String decimal = Integer.toString(i, 2);
            String decimal_fill = String.format("%09d", Integer.parseInt(decimal));
            decimal_array.add(decimal_fill);
        }
        return decimal_array.get(index);
    }

こちらはStringで引数に指定されたインデックス番号の文字列(2進数)を返すメソッドとなっています。 やっていることは非常にシンプルで、for文の「i」を1から30まで一つづつ「toString」で2進数化し、その進数を9桁の数字になるようにString.formatで整形して返す、というもの。 そしてテストするメソッドはこちらです。

public static String ClickHandler2(String args) {
        String url = "";
        String type = "";
//           IP取得
        try {
            InetAddress address = InetAddress.getLocalHost();
            url = "http://" + address.getHostAddress() + ":8888";
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        WebDriver driver = new ChromeDriver();
        WebDriverWait wait = new WebDriverWait(driver, 20);
        driver.get(url);
        WebElement start = driver.findElement(By.className("start-btn"));
        start.findElement(By.tagName("a")).click();
        if (driver.findElements(By.tagName("button")).size() != 0) {
            System.out.println(args);
            for (int z = 0; z < 10; z++) {
                if (driver.findElements(By.tagName("button")).size() != 0) {
                    List<WebElement> el = driver.findElements(By.tagName("button"));
                    WebElement el0 = el.get(0);
                    WebElement el1 = el.get(1);

                    switch (args.charAt(z)) {
                        case '0':
                            el0.click();
                            break;
                        case '1':
                            el1.click();
                            break;
                    }
                } else {
                    System.out.println("結果ページです");
                    WebElement h1 = driver.findElement(By.tagName("h1"));
                    String src = h1.findElement(By.tagName("img")).getAttribute("src");
                    type = src.substring(src.length() - 5, src.length() - 4);
                    System.out.println(type);
                }
            }
        }
        return type.toUpperCase();
    }

このメソッドは先ほどのarrayCreateで返された二進数の文字列を引数にして、その文字列が「0か1か」で9問目まで判別し、その判別結果によってボタンをクリックさせる、という内容になっています。 最終的に返されるのはtypeというString型の変数で、こちらが結果ページの「タイプ」です。 そしてテストケースはこちら。

    @Test public void test0() { Assert.assertEquals("R", ClickTest2.ClickHandler2(arrayCreate(0))); }

予想されるタイプを第一引数、そして先ほどのメソッドで返されるタイプを第二引数にしています。 現在テストケースはこれしか作成していませんが、なんとなく512まで作れそうな気だけはするような… それぞれのメソッドに関してはまた後日お話しします。 今回は初めてSeleniumを使ってみたら意外といろんなことができるんだなあ...というお話しでした!

イラレの個人的注意点をまとめてみた

 

さて、しばらくコードの話をしていたので今回はイラレについてお話しようと思います!

私は業務でデザイナーさんから送っていただくデザインを元にコーディングすることが多いのですが、その場合フォトショかイラレかのどちらかをいただきます。

その中でもイラレの方がなんとなーく迷うことがありそうなので備忘録がてら書いていこうとおもいます。

 

ダイレクト選択ツールで選択しようとしたら背景が持ってかれる...

直感的に使うとなると陥りやすいやつですね。

こちらはかなりシンプルで背景レイヤーにロックをかけるだけで解決できます。

また背景レイヤーだけでなく、選択したくないレイヤーや動かしたくないレイヤーにはあらかじめロックをかけておくといいかもですね。

クリッピングパスがかけられているレイヤーを余白なしで書き出したい!

普通にクリッピングパスがかけられているレイヤーを選択して書き出そうとすると、そのクリッピングがかけられている元のレイヤーのコンテンツは含まれませんが、元のレイヤー分の幅・高さで書き出されてしまうので余白が生まれてしまいます。

その際には、アートボードツールを使うと綺麗に書き出すことができます。

まずダイレクト選択ツールでクリッピングマスクがかけられているレイヤーを選択します。

そしてアートボードツール(mac:shift+O)に切り替え、そのレイヤーをもう一度クリックするとその選択したレイヤーでアートボードが作られます。

アートボードができたらあとは「書き出し」から「スクリーン用に書き出し」で書き出したいアートボードを選択して書き出せばOKです。

 

簡単な内容でしたが備忘録として残しておきます...

React.jsの環境をnpmで作ろう!APIからデータを取得する方法も実践!

 

今回は先延ばしにしていたReact.jsを使うための環境構築、そしてAPIからデータを取得して利用する方法についてご紹介していきたいと思います。

いや〜propsの理解についても苦労しましたが、何と言っても環境構築が一番手間取りましたね...

最近ではDockerなどを使って仮想環境を作成することもあるのですが、どうもその辺りが苦手でして(汗

とは言え、React.jsの場合はnpmで「create-react-app」というコマンドがあるので、それを知ってさえいれば苦労はしなさそうですが...

ということで今回はnpmで一からReactを利用できるようにするまで、そしてタスクランナーの設定までご紹介したいと思います!

さて、Reactの環境を作るために必要なものはなんなのでしょう?

純粋にReactのコードを動かすためなら必要なものは以下の二つです。

npm install react
npm install react-dom

これはreactとreact-domのパッケージを追加するためのコマンドですね。
しかし、これだけではReactのコードを記述することができてもjsxの記法しておりませんので、前回そして前々回に私が作成したようなrender()の中にHTML
を書くような記法は取ることができず、あくまでjsのネイティブ的な書き方をするしかありません。
でも、どうせなら可読性の高いjsxの記法をしたいですよね???(強制)
ということで、今回初めてjsの依存関係を整理してくれる「browserify」を使ってみました。

gulp.task('browserify', function() {
  browserify('./src/index.js', { debug: false })
    .transform(babelify,{presets: ['es2015', 'react']})
    .bundle()
    .on("error", function (err) { console.log("Error : " + err.message); })
    .pipe(source('bundle.js'))
    .pipe(gulp.dest('./dist'))
});

私はタスクランナーとしてGulpを使っているのですが、browserifyのタスク指定は上記の通りです。
最終的にindex.jsというコンポーネントをbrowserifyするのですが、このindex.jsは一般的にいちばん親のコンポーネントであるApp.jsのさらに親のコンポーネント
つまり関係性を表すとすれば↓のようになりますね。

index.js
 -App.js
  -Componet1.js

んー、ちょっと具体例がわかりにくいですかね...
本来であればApp.jsでbrowserifyをかけてもいいのですが、なんとなくスッキリしているのが好きなのでindex.jsというさらにラッパーなjsを作成しているような感じです。
ちょっとわかりづらそうなので一部コードを載せてみたいと思います。
index.js

import React from 'react'
import ReactDOM from 'react-dom'
import App from './component/App'

ReactDOM.render(
  <App />, document.getElementById('content')
);

Componet.js

mport React from 'react'
import {render} from 'react-dom'

class Question extends React.Component {

  render(){
    if(this.props.count > 0){
      return(
        <div  id="questions" className="questions">
        <button onClick={this.props.countHandler}>push</button>
        <p>{this.props.count}</p>
        {this.props.question.map((data,index)=>{
          if(index === this.props.count){
            return(
              <div key={`Q${index+1}`} id={`q${index+1}`} className="inner">
                <p key={index}>{data.text}</p>
                <img key={`imgQ${index+1}`} src={`../img/q0${index+1}.jpg`} />
                <div className="question">
                  <button className={data.question[0].type} onClick={this.props.answerCountHandler}>{data.question[0].text}</button>
                  <button className={data.question[1].type} onClick={this.props.answerCountHandler}>{data.question[1].text}</button>
              </div>
              </div>
            )
          }
          })
        }
        </div>
      )
    }
    else {
      return (null);
    }
  }
}

export default Question;

App.js

import React from 'react'
import {render} from 'react-dom'
import Question from './question'
import Start from './start'
import Result from './result'

class App extends React.Component {

  constructor(props) {
    super(props)
    this.state = {
      count: 0,
      questions: [],
      results: [],
      countType: [],
      userAnswers: [],
      done: false,
      type: '',
      hasError: false,
      isLoading: false,
    }
  }

//----------関数定義 st----------//

  componentDidMount() {
    this.fetchQuestionData('../data/data.json');
    this.fetchResultData('../data/result.json');
  }

  fetchQuestionData(url) {
  this.setState({ isLoading: true });
  fetch(url)
    .then((response) => {
      if (!response.ok) {
        throw Error(response.statusText);
      }
      this.setState({ isLoading: false });
      return response;
    })
    .then((response) => response.json())
    .then((data) => this.setState({ questions: data }))
    .catch(() => this.setState({ hasErrored: true }));
  }

  fetchResultData(url) {
  this.setState({ isLoading: true });
  fetch(url)
    .then((response) => {
      if (!response.ok) {
        throw Error(response.statusText);
      }
      this.setState({ isLoading: false });
      return response;
    })
    .then((response) => response.json())
    .then((data) => this.setState({ results: data }))
    .catch(() => this.setState({ hasErrored: true }));
  }

//----------関数定義 en----------//


  render() {
    if (this.state.hasError) {
      return <p>error</p>;
    }
    if (this.state.isLoading) {
      return <p>loading . . . </p>;
    }
        return (
        <div className="App">
          <Start count = {this.state.count} countHandler = {this.countHandler.bind(this)}/>

          <Result count = {this.state.count} result = {this.state.results} />

          <Question
           count = {this.state.count}
           question = {this.state.questions}
           countHandler = {this.countHandler.bind(this)}
           answerCountHandler = {this.answerCountHandler.bind(this)}
           />
        </div>
      );
    }
  }

export default App

かなり長くなってしまいましたが関係ないところは一応省きました。
コードの中身はとりあえず追わないでもらって、今みて欲しいところはimportとexportです。
見てもらえればわかると思うのですが、上記の中でindex.js以外は全てそのクラス自体をexportしています。
そしてApp.jsではComponet.jsのクラス「Question」をimportし、index.jsではそのApp.jsをimportしてReactDOMで最終的にimportしてきたApp.jsをrenderしています。
ぶっちゃけindex.jsを作る必要はあまりないのですが、実行クラスを完結にすることでなんとなくスッキリしますよね。
そして最終的にはこのindex.jsをbrowserifyすることで各コンポーネントとの依存関係を解決しています。
いやーbrowserify便利ですね。
さて、Reactの環境を作るのに必要な要点はこのreactのパッケージ、そしてコンポーネントごとに分けるならbrowserifyが必要なのですが、もちろん他にもインストールするべきパッケージは多々あります。
こちらのpackage.jsonをnpm installすればReactの環境は作れると思いますので、ぜひ試してみてください!

{
  "name": "npmreact",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "watch": "watchify -t babelify ./app.js -o ./build.js",
    "start": "browser-sync start --server --files='./*.html, ./*.js'"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "babel-core": "^6.26.3",
    "browser-sync": "^2.24.5",
    "browserify": "^16.2.2",
    "gulp": "^3.9.1",
    "gulp-autoprefixer": "^5.0.0",
    "gulp-babel": "^7.0.1",
    "gulp-sass": "^4.0.1",
    "gulp-sourcemaps": "^2.6.4",
    "gulp-uglify": "^3.0.0",
    "react": "^16.4.1",
    "react-dom": "^16.4.1",
    "vinyl-source-stream": "^2.0.0"
  },
  "devDependencies": {
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "babelify": "^8.0.0",
    "watchify": "^3.11.0"
  }
}

さて、Reactの環境構築についてはこのあたりにして、最後にAPIからデータをとって利用する方法についてご紹介します。
今回作成したのはgithubにあるAPIを叩いて、配列のnameだけをリストにしたものです。
codepen.io
ここで重要なのはやはりfetchですね。

Appクラス~~~
  componentDidMount() {
    this.fetchData('https://api.github.com/users/mismith0227/repos')
  }

  fetchData(url) {
    fetch(url)
      .then((response) => response.json())
    .then((responseData) => {
      this.setState({
        data: responseData,
      })
    })
  }

ここではfetchDataというメソッドを定義して、引数にAPIのurlを指定するようにしています。
ComponetDidMount()というのはReactのライフサイクルに関わるメソッドなのですが、これに関してはググってみてください。
さて、肝心のfetchですがデータの取り方や渡し方は普通のjsと同じですのでMDNでfetchを調べてみるといいと思います。
ただ普通とは違うのが最後の「setState()」ですね。
これで空配列のstate「data」にAPI で取得したものをセットしています。
これによってstateとしてAPIのデータを利用できるので、あとは前回と同じです。(map関数に関しては次の機会でお話したいと思います...)
このようにして、APIで叩いた結果をReactで利用できるようになるんですね。
実際に実行できるようになるまでは時間が少しかかってしまいましたが、コード自体はシンプルなのでぜひ上記コードにあるgitのAPIで試してみてください!

さて、今回はReactの環境構築とAPIを叩いてデータを利用する方法を見ていきました。
環境構築を一から行うのはやや骨が折れると思いますが、冒頭でもお話したようにcreate-react-appという便利なコマンドがあるようなので、今ならそこまで時間がかからないのかもしれませんね。
またAPIも簡単に利用できるのでReactでできることの幅も一気に広がると思います。
参考になるかはわかりませんが、私が作成したものを煮るなり焼くなりして動きを掴んでもらえればと思います...
では次回は「Reactでの注意点やmap関数について」をお送りしよう(変わるかも...)と思いますので次回もよろしくお願いいたします!