20190724のReactに関する記事は9件です。

【初心者】React&Redux入門を理解するための超入門/環境構築編

未来電子テクノロジー株式会社でインターンをしている文系大学1回生です。
半月ほどReactとReduxの勉強をしています。
理解がなかなか難しいので、勉強したこと、自分なりのポイントをアウトプットしていきます。

Reactをブラウザに表示するまでの過程が難しかったのでまとめます。

React at CodePen を用いる

これが一番簡単です。
環境構築なしで、すぐにReactを試せます。

create-react-app

$ cd desktop
$ create-react-app mirai
デスクトップにmiraiフォルダができる。
$ cd mirai
$ npm start
で、ブラウザに表示できる。(ロゴがクルクル)

しかし、このままではコードがややこしい。
自分でいじろうとした時に、どこをいじれば良いか分からない。
そこで、コードをスッキリさせる。

mirai/src/App.js
import React from 'react';

function App() {
  return (
          <div>
            Learn React
          </div>
  );
}

export default App;
mirai/src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import * as serviceWorker from './serviceWorker';

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

serviceWorker.unregister();
mirai/public/index.js
<title>React App</title>

<div id="root"></div>

こうすると、ブラウザには、Learn Reactと表示されるだけになる。
コードがスッキリして、どこをいじればいいか分かりやすい。

HTMLファイル1枚

実はReactは、HTMLファイル1枚でブラウザ表示ができる。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8" />
    <title>React</title>
    <script src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>
</head>
<body>

    <div id="root"></div>

    <script type="text/babel">
    let dom = document.querySelector('#root');

    let el = (
        <div>
            <h1>Learn React</1>
        </div>
    );

     ReactDOM.render(el, dom);
    </script>
</body>
</html>

ブラウザには、Learn Reactと表示される。
あとは、scriptタグ内をいじっていけば良い。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【初心者】React&Redux入門を理解するための超入門

未来電子テクノロジー株式会社でインターンをしている文系大学1回生です。
半月ほどReactとReduxの勉強をしています。
理解がなかなか難しいので、勉強したこと、自分なりのポイントをアウトプットしていきます。

ReactやReduxのコードの意味が分からないのは、jsの基礎が抜けているのも一つの原因でした。
そこで、jsの基礎をもう一度確認しました。

jsの基礎

w3schoolscom

英語ですが、とても分かりやすいです。
実際に手を動かして基礎の理解を深められます。

ポイント

document.getElementById("hoge")

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript in Body</h2>

<p id="demo"></p>

<script>
document.getElementById("demo").innerHTML = "My First JavaScript";
</script>

</body>
</html> 

Reactにも出てきます。
任意のHTMLタグで指定したIDにマッチするドキュメント要素を取得するメソッドです。

オブジェクト

<script>
// Create an object:
var car = {type:"Fiat", model:"500", color:"white"};

// Display some data from the object:
document.getElementById("demo").innerHTML = "The car type is " + car.type;
</script>

Reactでは、複数のスタイルを設定するために、スタイル名をプロパティとしたオブジェクトのリテラルを記述するときや、ステートの値を設定するときなどに必要な知識です。

new演算子の使い方と生成方法まとめ!
これもオブジェクトの勉強になった。

公式ドキュメント

Reactにも出てくる構文の基礎を固めるのに最適です。

ポイント

this

var myObject = {
  value: 10,
  show: function() {
    console.log(this.value);
  }
}
myObject.show(); // 10

上記は、単にメソッドの呼び出しを行っています。
しかし、thisはそんなに生易しいものでは無いようです。

thisって何?使い方を覚えて、JavaScriptをもっと楽しく使おう!

windowオブジェクトとグローバルの実態について

strictモードの使い方を徹底解説!

applyって何だ?callとの違いまで徹底解説

JavaScriptの「this」は「4種類」??

これらの記事を理解して少しthisについて詳しくなったと思います。
windowオブジェクトとグローバルの実態なんて知らなかった。。。

super

class Animal {
  constructor(name) {
    console.log('親クラスのコンストラクタ');
    this.name = name;
  }

  speak() {
    console.log('親クラスのspeakメソッド');
  }
}

class Dog extends Animal {
  constructor(name, age) {
    console.log('子クラスのコンストラクタ');
    super(name);
    this.age = age;
  }

  speak() {
    super.speak();
    console.log('子クラスのspeakメソッド');
  }
}
const dog = new Dog('ポチ', 1);
dog.speak();
console.log('名前: ' + dog.name + '年齢: ' + dog.age); //"名前: ポチ年齢: 1"

constructor : 「super()」で親クラスのconstructorを実行する。
constructor以外のメソッド : 「super.メソッド名()」で親クラスのメソッドを実行する。

【JavaScript】superの使い方【クラス継承】

bind

function say(){
 console.log("こんにちは。" + this + "です");
}
var taro = say.bind("hoge");
taro(); //こんにちは。hogeです
function sum(x, y, z){
        return x + y + z;
      }
      var keisan = sum.bind(null, 10, 20, 30);
      console.log(keisan()); //60

関数に対してthisや引数を指定することができるメソッド。

JavaScriptでbindメソッドを使う方法

非同期処理、コールバック関数

redux-saga等の理解に不可欠。

const promise = new Promise((resolve, reject) => {
    setTimeout(() => { 
        console.log('hello');
        resolve();
    }, 500);
});

promise.then(() => console.log('world!'));

Promiseとasync/awaitでJavaScriptの非同期処理をシンプルに記述する

XMLHTTPRequest

Objectのgetとsetについて理解をまとめる

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【初心者】React&Redux入門を理解するための超入門/jsの基礎編

未来電子テクノロジー株式会社でインターンをしている文系大学1回生です。
半月ほどReactとReduxの勉強をしています。
理解がなかなか難しいので、勉強したこと、自分なりのポイントをアウトプットしていきます。

ReactやReduxのコードの意味が分からないのは、jsの基礎が抜けているのも一つの原因でした。
そこで、jsの基礎をもう一度確認しました。

jsの基礎

w3schoolscom

英語ですが、とても分かりやすいです。
実際に手を動かして基礎の理解を深められます。

ポイント

document.getElementById("hoge")

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript in Body</h2>

<p id="demo"></p>

<script>
document.getElementById("demo").innerHTML = "My First JavaScript";
</script>

</body>
</html> 

Reactにも出てきます。
任意のHTMLタグで指定したIDにマッチするドキュメント要素を取得するメソッドです。

オブジェクト

<script>
// Create an object:
var car = {type:"Fiat", model:"500", color:"white"};

// Display some data from the object:
document.getElementById("demo").innerHTML = "The car type is " + car.type;
</script>

Reactでは、複数のスタイルを設定するために、スタイル名をプロパティとしたオブジェクトのリテラルを記述するときや、ステートの値を設定するときなどに必要な知識です。

new演算子の使い方と生成方法まとめ!
これもオブジェクトの勉強になった。

アロー関数

普通の関数。

hello = function() {
  return "Hello World!";
}

アロー関数。

hello = () => {
  return "Hello World!";
}

リターン省略。

hello = () => "Hello World!";

引数あり。

hello = (val) => "Hello " + val;

()省略。

hello = val => "Hello " + val;

コールバック関数

function doTwice(func) {
  func(); // 1回目!
  func(); // 2回目!
}

// あいさつするだけの関数
function hello() {
  console.log('Hello!');
}

// あいさつを2回実行する
doTwice(hello); //Hello!
                //Hello!

hello:コールバック関数 渡すときは()をはずす。
doTwice:高階関数(関数を受け取る関数)

map

構文

var array = [ 配列データ ];

array.map( コールバック関数 );

基本的な使い方

var items = [1,2,3,4,5];

var result = items.map(function( value ) {

    //配列の各要素を2倍にする
    return value * 2;

});

console.log( result ); //[2, 4, 6, 8, 10]

mapとアロー関数

var result = items.map(( value ) => {

    //配列の各要素を2倍にする
    return value * 2;

});

Spread Operator

配列

const hoge = [2, 3];
console.log([1, ...hoge, 4, 5]) //[1, 2, 3, 4, 5]

オブジェクト

const fuga = {name: 'Taro' , age: 25 };
const piyo = {name: 'Jiro' , location : 'Tokyo'};
console.log({...fuga, ...piyo}); //{ name: 'Jiro', age: 25, location: 'Tokyo'}

slice

var array = ['メロン', 'リンゴ', 'イチゴ', 'バナナ'];

//開始位置を指定
var result1 = array.slice( 1 );

//開始位置と終了位置を指定
var result2 = array.slice( 1, 3 );

//そのまま返す
var result3 = array.slice( );

console.log( result1 ); //["リンゴ", "イチゴ", "バナナ"]
console.log( result2 ); //["リンゴ", "イチゴ"]
console.log( result3 ); //["メロン", "リンゴ", "イチゴ", "バナナ"]

そのまま返すなんて意味がないと思うかもしれない。
しかし、Reduxで配列操作をする時に必要なのだ!

concat

var array1 = ['ho', 'ge'];
var array2 = ['wa', 'fu'];
var result = array1.concat(array2);

console.log(result);// ho,ge,wa,fu

配列を結合できる。
とにかくReduxでは配列を直接いじりたくない。

イベント

<button onclick="document.getElementById('demo').innerHTML = Date()">The time is?</button>

上記はonclickイベント。クリック時に発動。
他に、onchange onmouseover onkeydownなどがある。

公式ドキュメント

Reactにも出てくる構文の基礎を固めるのに最適です。

ポイント

this

var myObject = {
  value: 10,
  show: function() {
    console.log(this.value);
  }
}
myObject.show(); // 10

上記は、単にメソッドの呼び出しを行っています。
しかし、thisはそんなに生易しいものでは無いようです。

thisって何?使い方を覚えて、JavaScriptをもっと楽しく使おう!

windowオブジェクトとグローバルの実態について

strictモードの使い方を徹底解説!

applyって何だ?callとの違いまで徹底解説

JavaScriptの「this」は「4種類」??

これらの記事を理解して少しthisについて詳しくなったと思います。
windowオブジェクトとグローバルの実態なんて知らなかった。。。

super

class Animal {
  constructor(name) {
    console.log('親クラスのコンストラクタ');
    this.name = name;
  }

  speak() {
    console.log('親クラスのspeakメソッド');
  }
}

class Dog extends Animal {
  constructor(name, age) {
    console.log('子クラスのコンストラクタ');
    super(name);
    this.age = age;
  }

  speak() {
    super.speak();
    console.log('子クラスのspeakメソッド');
  }
}
const dog = new Dog('ポチ', 1);
dog.speak();
console.log('名前: ' + dog.name + '年齢: ' + dog.age); //"名前: ポチ年齢: 1"

constructor : 「super()」で親クラスのconstructorを実行する。
constructor以外のメソッド : 「super.メソッド名()」で親クラスのメソッドを実行する。

【JavaScript】superの使い方【クラス継承】

bind

function say(){
 console.log("こんにちは。" + this + "です");
}
var taro = say.bind("hoge");
taro(); //こんにちは。hogeです
function sum(x, y, z){
        return x + y + z;
      }
      var keisan = sum.bind(null, 10, 20, 30);
      console.log(keisan()); //60

関数に対してthisや引数を指定することができるメソッド。

Reactでは、this.hogehoge = this,hogehoge.bind(this);のように登場。

JavaScriptでbindメソッドを使う方法

非同期処理、コールバック関数

redux-saga等の理解に不可欠。

const promise = new Promise((resolve, reject) => {
    setTimeout(() => { 
        console.log('hello');
        resolve();
    }, 500);
});

promise.then(() => console.log('world!'));

Promiseとasync/awaitでJavaScriptの非同期処理をシンプルに記述する

XMLHTTPRequest

Objectのgetとsetについて理解をまとめる

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【初心者】React&Redux入門を理解するための超入門/jsの基礎編

未来電子テクノロジー株式会社でインターンをしている文系大学1回生です。
半月ほどReactとReduxの勉強をしています。
理解がなかなか難しいので、勉強したこと、自分なりのポイントをアウトプットしていきます。

ReactやReduxのコードの意味が分からないのは、jsの基礎が抜けているのも一つの原因でした。
そこで、jsの基礎をもう一度確認しました。

jsの基礎

w3schoolscom

英語ですが、とても分かりやすいです。
実際に手を動かして基礎の理解を深められます。

ポイント

document.getElementById("hoge")

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript in Body</h2>

<p id="demo"></p>

<script>
document.getElementById("demo").innerHTML = "My First JavaScript";
</script>

</body>
</html> 

Reactにも出てきます。
任意のHTMLタグで指定したIDにマッチするドキュメント要素を取得するメソッドです。

オブジェクト

<script>
// Create an object:
var car = {type:"Fiat", model:"500", color:"white"};

// Display some data from the object:
document.getElementById("demo").innerHTML = "The car type is " + car.type;
</script>

Reactでは、複数のスタイルを設定するために、スタイル名をプロパティとしたオブジェクトのリテラルを記述するときや、ステートの値を設定するときなどに必要な知識です。

new演算子の使い方と生成方法まとめ!
これもオブジェクトの勉強になった。

公式ドキュメント

Reactにも出てくる構文の基礎を固めるのに最適です。

ポイント

this

var myObject = {
  value: 10,
  show: function() {
    console.log(this.value);
  }
}
myObject.show(); // 10

上記は、単にメソッドの呼び出しを行っています。
しかし、thisはそんなに生易しいものでは無いようです。

thisって何?使い方を覚えて、JavaScriptをもっと楽しく使おう!

windowオブジェクトとグローバルの実態について

strictモードの使い方を徹底解説!

applyって何だ?callとの違いまで徹底解説

JavaScriptの「this」は「4種類」??

これらの記事を理解して少しthisについて詳しくなったと思います。
windowオブジェクトとグローバルの実態なんて知らなかった。。。

super

class Animal {
  constructor(name) {
    console.log('親クラスのコンストラクタ');
    this.name = name;
  }

  speak() {
    console.log('親クラスのspeakメソッド');
  }
}

class Dog extends Animal {
  constructor(name, age) {
    console.log('子クラスのコンストラクタ');
    super(name);
    this.age = age;
  }

  speak() {
    super.speak();
    console.log('子クラスのspeakメソッド');
  }
}
const dog = new Dog('ポチ', 1);
dog.speak();
console.log('名前: ' + dog.name + '年齢: ' + dog.age); //"名前: ポチ年齢: 1"

constructor : 「super()」で親クラスのconstructorを実行する。
constructor以外のメソッド : 「super.メソッド名()」で親クラスのメソッドを実行する。

【JavaScript】superの使い方【クラス継承】

bind

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

非エンジニアの社長にReactとは何かを説明する①

非エンジニアの社長にReactとは何かを説明する

最近、エンジニアのデイリーMTGを始めたのですが、ありがたいことに非エンジニアの社長もオブザーバーとして参加してくれています。
とはいえ、やはりエンジニアのデイリーMTGの内容となると技術的な内容が多くなるので非エンジニアの面々には分からない部分が多いはずです。
このままMTGを続けるのは申し訳ないですし、非エンジニアにも分かるように説明するという視点で記事を書いてみるのも面白いかなと思うので、つらつらと書いてみようかと思います。
まず、最近主に扱っているReactについて。

なお、説明がややこしくなるのを避けるため、厳密に正確な説明をすることは放棄している部分があります。
悪しからず。

ブラウザとjavascript

いきなりReactの説明を始めることは出来ないので、その前提となるブラウザとjavascriptから説明を始めます。

ブラウザ

ブラウザは、ChromeやInternetExploler,Edgeと言ったWebページを閲覧するのに使っているものです。

さて、このブラウザにはエンジニアは当たり前のように使うものの、一般の方はまず使わない機能が搭載されています。
何らかのページを開いている状態で「F12」ボタンを押して見てください。

おそらく、開発者コンソールとかDevToolとかそんな感じの名前のものが出てくるかと思います。
画面上部にタブがあるので、Elementあるいは要素(ブラウザによって表示は違います)を選んでください。

そうすると、以下のような感じに<>で囲まれた文字が羅列されていると思います。

htmlサンプル.png

この一見、よく分からない文字列の羅列がいわゆるHTMLと呼ばれる形式で書かれたページのソースで、ブラウザ上に表示されているWebページの元です。
コンテンツとして載せる画像や動画は別として、Webページは基本的にこのHTML形式のデータをブラウザが読み取って表示しています。
(ちなみに、Webページ上の要素を右クリックして、「検証」を選択すると、その要素がソース上の何に相当するのか表示してくれます。興味があれば是非)
大雑把な言い方をすれば、Web系のエンジニアはこの文字列を作ったり操作したりするプログラムを書くのが仕事というわけです。

JavaScript

先ほど、「WebページはHTML形式のデータをブラウザが読み取って表示しているもの」と説明しましたが、
実は、HTML形式のデータだけではWebページはほとんどあるいは全く動きがないものになります。
具体的には、阿部寛のホームページのような感じです。
リンクを踏んでページを切り替える以外に画面を変化させる方法がありません。

ただ、このようなページは極めて例外的です。実際、普段皆さんがご覧になっているWebページは、もっと色々な動きがついているはずです。
例えば、検索欄に何か打ち込んだらサジェストが出たり、スクロールしたら徐々に要素が出てきたりとかですね。

これがどうやって実現されているかと言うと、ブラウザ上で「JavaScript」という言語が動き、Htmlの内容を書き換えることによって実現されています。
実際、先ほど紹介した開発者ツールのElementを見ながら画面上の動きを起こすと、
どこかしら要素に変化があることがわかるかと思います。(ものによっては一か所値が書き換わるだけで分かりにくかったりもしますが…)

WebページのUI・UXがどんどんリッチになっていっている現代、このJavaScriptの役割もますます大きくなってきており、いわゆる「フロントエンドエンジニア」と呼ばれる人々は主にこのJavaScriptを扱っています。

そして、今回説明しようとしているReactはこのjavascriptをうまく使うための便利な道具集(ライブラリ)の一つです。

Reactは名前しか出てきていませんが、長くなってきたのでこの辺りで。
次回に続きます。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

React.useEffectでfetchをするhookの実装方法

はじめに

本記事は過去記事のまとめです。とはいえ、スクリーンキャストは新しい内容です。

スクリーンキャスト

ゆっくり見るには、リンクを開いて、右矢印を押して進めてください。

各ステップの記事

おわりに

当初の記事に載せたコードもほぼ同じものです。色々改善して最後に作成したスクリーンキャストのコードが分かりやすくなっていると思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Create React AppからStorybookの追加が超簡単だった。

概要

ReactでStorybook使ってみたくて、色々調べてた結果、
設定面倒なのかなーと思ってたらCreate React Appからの追加が超簡単だったという話です。

環境構築

今回はyarnでゴリゴリ入れていきましょう。

yarn global add create-react-app
yarn create react-app sample-storybook
cd sample-storybook
yarn add storybook
yarn storybook

ここまで来ると、「お?Create React Appで作ったプロジェクトやんけ!」
と勝手に解釈してくれて、良い感じに雛型を作ってくれます。超便利ですね。

再度yarn storybookを叩くと、http://localhost:9009でStorybookの
サーバーが立ち上がります。以上です。

コンポーネント追加

Material-UIのボタンを追加してみます。
(実際は自作のコンポーネントを追加するような使い方になると思いますが)

yarn add @material-ui/core
src/stories/index.js
import React from 'react';

import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { linkTo } from '@storybook/addon-links';

import { Button, Welcome } from '@storybook/react/demo';

+ import MaterialButton from '@material-ui/core/Button';

storiesOf('Welcome', module).add('to Storybook', () => (
  <Welcome showApp={linkTo('Button')} />
));

storiesOf('Button', module)
  .add('with text', () => (
    <Button onClick={action('clicked')}>Hello Button</Button>
  ))
  .add('with some emoji', () => (
    <Button onClick={action('clicked')}>? ? ? ?</Button>
  ))
+  .add('material', () => (
+    <MaterialButton
+      variant="contained"
+      color="primary"
+      onClick={action('clicked')}
+    >
+      Primary
+    </MaterialButton>
+  ));

ホットリロードで画面が更新されています。良いですね。
image.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

43種ものデータ変形がブラウザだけでできる『transform』が便利そう

transformは、なんでもデータ変形サービスで、JSONからYAML、HTMLからJSXへの変形はもちろん、JSONやGraphQLのIDLからTypeScriptのinterfaceを生成するようなものまで手広く対応しているサービスだ。

https://transform.tools/

transform.tools2.gif

特別なツールをインストールする必要はなくブラウザだけで動作する。

現在、43種類のデータ変形に対応しており、対応している変形パターンは下記のとおり:

  1. SVG to JSX
  2. SVG to React Native
  3. HTML to JSX
  4. JSON to React PropTypes
  5. JSON to Flow
  6. JSON to GraphQL
  7. JSON to TypeScript
  8. JSON to MobX-State-Tree Model
  9. JSON to Sarcastic
  10. JSON to io-ts
  11. JSON to Rust Serde
  12. JSON to Mongoose Schema
  13. JSON to Big Query Schema
  14. JSON to MySQL
  15. JSON to Scala Case Class
  16. JSON to Go Struct
  17. JSON to YAML
  18. JSON to JSDoc
  19. JSON Schema
  20. JSON to TypeScript
  21. JSON to OpenAPI Schema
  22. CSS to JS Objects
  23. CSS to template literal
  24. JavaScript to JSON
  25. GraphQL to TypeScript
  26. GraphQL to Flow
  27. GraphQL to JAVA
  28. GraphQL to Resolvers Signature
  29. GraphQL to Introspection JSON
  30. GraphQL to Schema AST
  31. GraphQL to Fragment Matcher
  32. GraphQL to Components
  33. GraphQL to TypeScript MongoDB
  34. JSON-LD to N-Quads
  35. JSON-LD to Expanded
  36. JSON-LD to Compacted
  37. JSON-LD to Flattened
  38. JSON-LD to Framed
  39. JSON-LD to Normalized
  40. Flow to Typescript
  41. XML to JSON
  42. YAML to JSON
  43. Markdown to HTML

どんなときに使うといいか?

例えば

  • Reactコンポーネントを作っていて、素材となるHTMLをJSXにしたいとき。
  • JSON APIのレスポンスをTypeScriptで扱う際、レスポンスJSONの型をTypeScriptのinterfaceで定義したいとき
    • ScalaやGoでも同様

こういったシーンで、手っ取り早く仕事を済ますときに使えそう。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

React+Typescriptでカウンターアプリ作成に難航したお話〜3の倍数の時モーダル出現が難しい訳ないじゃん....〜

こんなものを作りました。

Reactの基本を学ぶためにカウターを作りました。
3の倍数のとき、モーダルが立ち上がります。全体を通して簡単でしたが、苦労した点がありました。
Image from Gyazo

☆Special Thanks☆

React Component ライフサイクル ひとめぐり (CodeSandbox 付き)

ReactでsetStateをすぐに反映させる方法…

js STUDIO 【componentDidUpdate】

信じられない...ライフサイクルを考えて実装しないといけないなんて...

[+1]を押下すると、カウントの値が1づつ増える。増えた値を判定してその値が3の倍数であったらモーダルを表示するフラグをtrueにする。この流れを1つの関数として以下のように実装しました。

App.tsx
increment() {
 this.setState(prevState => ({
  count: prevState.count + 1, }));
  if(this.state.count && this.state.count % 3 === 0){
   this.setState({isModalOpen: true});
  }
}

すると...
image.png

信じられない4が3の倍数だなんて...(違う)

setStateでcountを変えても、全てを一気に書き換えるというsetStateの特性上、this.state.countを直後に呼び出してもそのstateは更新前の状態になっている。これが想い通りにならない原因のようだった。

そこで、コンポーネントの更新を終えてすぐに関数を呼び出したい時(DOMを操作したい時)は、componentDidUpdate を使うといいよ、ということでしたので試しました。
React入門でこのカウンターを作っていたので「ライフサイクルとかとりあえずいいやっ」そんな軽い気持ちで読み飛ばしていたせいで引っかかってしまいました。

まさかの落とし穴...無限ループに陥るべからず...

componentDidUpdateを使って、countに[+1]づつ足していき、値が3の倍数かどうかを判定するという実装をしようと試みた矢先の出来事でした。

consoleにはけたたましい数のエラーがっ(。゚(゚´Д`゚)゚。)52回でループが止まってよかった...
こんなエラーも出てました。

Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.

ふむふむ。。なるほど。(Google先生によると)

最大更新深度を超えました。これは、コンポーネントがcomponentWillUpdateまたはcomponentDidUpdate内でsetStateを繰り返し呼び出すと発生する可能性があります。 Reactは、無限ループを防ぐために入れ子になった更新の数を制限します。

ということのようだが....

何だろう...このコードの何がいけないの?...

App.tsx
increment() {
 this.setState(prevState => ({
  count: prevState.count + 1, }));
 }

 componentDidUpdate(prevProps: object, prevState: AppState){
   this.judge(prevState.count + 1); //←問題はこの部分に条件式がないこと
}

 judge(num: number) {
   if(this.state.count && this.state.count % 3 === 0) {
    this.setState({isModalOpen: true});
   }
 }

【上記コードの問題点】
(1)[+1]を押下する

(2)prevState.count+1 した値をcontへ渡す

(3)componentDidUpdate内で、countの値を判定し、3の倍数(かつ0以外)のときモーダル表示フラグisModalOpenをtrueにする

(3)において、judge関数内で状態変更がなされた後、その状態の変更によって再度componentDidUpdateがトリガされ、setStateによって状態が再びtrueに設定される。これにより、componentDidUpdateが何度もトリガされる。

このようになっており無限ループが始まってしまう問題をはらんでいます。Reactは無限ループを防ぐ仕様になっていてよかった。問題ということなので、下記の【実行したいこと】をもとに問題箇所のコードを書き直しました。

App.tsx
componentDidUpdate(prevProps: object, prevState: AppState){
 if (prevState.count !== this.state.count) {
  this.judge(prevState.count + 1);
 }
}

【実行したいこと】
・[+1]を押下する

・押下する前の値prevState.countを補完する

・prevState.countと押下後の値countを比較して違っている場合だけjudge()を発火させる(★)

・countが3の倍数(かつ0以外)のときモーダル表示フラグisModalOpenをtrueにする

問題の箇所に、(★)の条件式を追加して解決しました。

まとめ

Reactの勉強を始めたとき、ライフサイクルについてはサラーっと流してしまいましたが、すぐに必要な場面に出会うことができ大変理解が深まったと思います。

初心者だからと言って安易に読み飛ばしてはいけません!
入門書だからここは飛ばしていいよなんていう甘い言葉を鵜呑みにしてはいけません!!!

この記事が、桂三度さん思い出すきっかけになれれば幸いです。

発展課題

5の倍数だけ犬っぽくなるを実装する

まとめのコード

(※classNameは省いています)

App.tsx
import React, { Component } from 'react';
import { Card, Statistic } from 'semantic-ui-react';

import './App.css';

interface AppState {
  count: number;
  isModalOpen: boolean;
}

class App extends Component<{}, AppState> {
  constructor(props: {}) {
    super(props);
    this.state = {
      count: 0,
      isModalOpen: false,
    }
  }

  modalOpen() {
    this.setState({isModalOpen: true});
  }

  modalClose() {
    this.setState({isModalOpen: false});
  }

  increment() {
    this.setState(prevState => ({
      count: prevState.count + 1, }));
  }

  componentDidUpdate(prevProps: object, prevState: AppState){
    if (prevState.count !== this.state.count) {
      this.judge(prevState.count + 1);
    }
  }

  decrement() {
    this.setState(prevState => ({
    count: prevState.count - 1, }));
  }

  judge(num: number) {
    console.log(this.state.count);
    if(this.state.count && this.state.count % 3 === 0) {
      this.setState({isModalOpen: true});
    }
  }

  render() {
    const { count } = this.state;
    let modal;

    if(this.state.isModalOpen) {
      modal = (
        <div className="modal">
          <div className="modal-inner">
            <div className="modal-hedder">3の倍数お知らせBot</div>
            <div className="modal-value">
              <h2>{count}</h2>
              <p>{count}3の倍数です。</p>
            </div>
            <button onClick={() => {this.modalClose()}}>
              とじる
            </button>
          </div>
        </div>
      )
    }

    return (
      <div>
        {modal}
        <header>
          <h1>カウンター</h1>
        </header>
        <Card>
          <Statistic>
            <Statistic.Value>
            {count}
            </Statistic.Value>
          </Statistic>
          <Card.Content>
            <div>
              <button onClick={() => this.decrement()}> -1</button>
              <button onClick={() => this.increment()}>+1 </button>
            </div>
          </Card.Content>
        </Card>
      </div>
    );
  }
}

export default App;

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む