onsen code monkey

個人的な日記とプログラミング備忘録です

【React】Reactの基礎知識を学習した④(ライフサイクルメソッド)

前回
hitoto28.hatenablog.com


コンポーネントの状態の変化(ライフサイクル)により発火するメソッドをライフサイクルメソッドという。

Reactのライフサイクルメソッドには以下の7種類がある。


componentWillMount()
コンポーネントがマウント(配置)される直前に呼び出されるメソッド。

componentDidMount()
コンポーネントがマウント(配置)された直後に呼び出されるメソッド。
このメソッド内では描画されたDOMにアクセスすることができる。

componentWillReceiveProps()
コンポーネントが受け取るpropsが変化した場合に呼び出されるメソッド。

shouldComponentUpdate()
stateもしくはporpsが変更された際のコンポーネントの再描画前に呼び出されるメソッド。
このメソッドでtrueを返した場合はコンポーネントは再描画され、falseを返した場合は再描画されない。
パフォーマンスの観点から再描画を抑制したい場合に利用される。

componentWillUpdate()
コンポーネントの再描画前に呼び出されるメソッド。
前述のshouldComponentUpdate()でfalseを返している場合はこのメソッドは呼び出されない。

componentDidUpdate()
コンポーネントが再描画された直後に呼び出されるメソッド。
このメソッド内では再描画されたDOMにアクセスすることができる。

componentWillUnmount()
コンポーネントがアンマウント(DOMから削除)される直前に呼び出されるメソッド。


以下サンプルコード

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';

//コンポーネントの作成
class Number extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      stateVal : 0
    };
    this.incrementState = this.incrementState.bind(this)
  }
  //Stateの加算
  incrementState(){
      this.setState({
        stateVal : this.state.stateVal+1
      });
  }
  componentWillMount(){
    console.log("コンポーネントのマウント前")
  }
  componentDidMount(){
    console.log("コンポーネントのマウント後")
  }
  componentWillReceiveProps(){
    console.log("コンポーネントが受け取るpropsが変化")
  }
  shouldComponentUpdate(){
    console.log("コンポーネントがアップデートされる前1")
    return true;
  }
  componentWillUpdate(){
    console.log("コンポーネントがアップデートされる前2")
  }
  componentDidUpdate(){
    console.log("コンポーネントがアップデートされた後")
  }
  componentWillUnmount(){
    console.log("コンポーネントがアンマウントされた後")
  }
  render() {
    return (
      <div>
        <p>props:{this.props.propVal}</p>
        <p>state:{this.state.stateVal}</p>
        <input type="button" value="stateの加算" onClick={this.incrementState} />
      </div>
    )
  }
};
class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      propVal : 0,
      isComponent :false
    };
    this.incrementProps = this.incrementProps.bind(this);
    this.mountComponent = this.mountComponent.bind(this);
  }
  //propsの加算
  incrementProps(){
      this.setState({
        propVal : this.state.propVal+1
      });
  }

  mountComponent(){
      this.setState({
        isComponent : !this.state.isComponent
      });
  }


  render() {
    return (
      <div>
        <input type="button" value="Numberコンポーネントのマウント切り替え" onClick={this.mountComponent} /><br />
        {(() => {
          if (this.state.isComponent) {
            return <Number propVal={this.state.propVal} />;
          }else{
            return null
          }
        })()}
        <input type="button" value="propsの加算" onClick={this.incrementProps} /><br />

      </div>
    )
  }
};
 //コンポーネントの描画
ReactDOM.render(
  <MyComponent />,
  document.getElementById('root')
);


ここまでくればあとは調べながらやればなんとかなりそうなので予習は一旦終了。
また詰まったら参考サイト様のお世話になろう。



↓参考サイト様
Reactのライフサイクル – React入門 - to-R Media

【React】Reactの基礎知識を学習した③(イベント)

前回
hitoto28.hatenablog.com


イベント

入力したテキストをonClickイベントで反映させるサンプル

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';

//コンポーネントの作成
class SampleComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      state1 : null
    };
  }
  //テキストの設定
  setSampleText(){
      this.setState({
        state1 : this.refs.sampleText.value
      });
      this.refs.sampleText.value='';
  }
  render() {
    return (
      <div>
        <p>入力結果:{this.state.state1}</p>
        <input type="text" ref="sampleText"/>
        <input type="button" value="入力" onClick={this.setSampleText.bind(this)}/>
      </div>
    )
  }
};
 //コンポーネントの描画
ReactDOM.render(
  <SampleComponent />,
  document.getElementById('root')
);

流れとしては以下の通り

  1. コンストラクタでstate1というStateを設定
  2. JSX内のonClickイベントでsetSampleText関数を実行
  3. setSampleText関数でstate1にテキストボックスの値を設定
  4. 入力結果にstate1の値を描画

注目すべき点は、JSX内のonClickイベントで発火するthis.setMyText.bind(this)の部分。
メソッド内でコンポーネント内にアクセスするためにはbind(this)の記述が必要らしい。
ただし、JSX内でbind(this)を記述すると描画のたびに関数を生成するのでスマートではない。

省略するためにはコンストラクタ内に以下のように記述する。

constructor(props) {
  super(props);
  this.state = {
    state1 : null
  };
  this.setSampleText = this.setSampleText.bind(this);
}


↓参考サイト様
Reactのイベント設定 – React入門 - to-R Media

【React】Reactの基礎知識を学習した②(Props/State)

前回
hitoto28.hatenablog.com


PropsとState
Reactコンポーネントがデータを受け取ったり表示したりするための方法。

Props・・・コンポーネント利用時に属性として設定できる値
State・・・コンポーネントが持っている状態

Propsは不変、Stateは可変のデータを扱う。
またStateの値を更新するとコンポーネントのrender()メソッドが実行され再描画される。


Propsの基本的な使い方
以下はSampleComponentというコンポーネントにPropsName1とPropsName2という2つのPropsを設定している。
設定したPropsはSampleComponent内のメソッドでthis.propsオブジェクトで利用できる。

//コンポーネントの作成
class SampleComponent extends React.Component {
  render() {
    return (
      <div>
        props1 : {this.props.PropsName1}
        props2 : {this.props.PropsName2}
      </div>
    )
  }
};
//コンポーネントの描画
ReactDOM.render(
  <SampleComponent PropsName1="PropsValue1" PropsName2="PropsValue2" />,
  document.getElementById('root')
);

Stateless Functionsで利用する場合、引数にpropsとして定義する。

//コンポーネントの作成
function SampleComponent(props) {
  return (
    <div>
      props1 : {props.PropsName1}
      props2 : {props.PropsName2}
    </div>
  )
};
//コンポーネントの描画
ReactDOM.render(
  <SampleComponent PropsName1="PropsValue1" PropsName2="PropsValue2" />,
  document.getElementById('root')
);

f:id:hitoto28:20180918041029p:plain
↑正常にデプロイできればこのように表示されるはず
改行コードを入れたいところだが一手間かかりそうなので今回はパス


Propsをスプレット演算子でまとめて展開
スプレッド演算子(…)を用いてオブジェクトを展開して設定することもできる。
定義したいPropsが複数ある場合は以下のようにオブジェクトとして定義しておき、まとめてコンポーネントに引き渡す。

//コンポーネントの作成
function SampleComponent(props) {
  return (
    <div>
      props1 : {props.PropsName1}
      props2 : {props.PropsName2}
    </div>
  )
};
//Propsの定義
const myProps = {
  PropsName1 : 'aaa',
  PropsName2 : 'bbb'
}
//コンポーネントの描画
ReactDOM.render(
  <SampleComponent {...myProps} />,
  document.getElementById('root')
);


defaultPropsで初期値を設定
defaultPropsでPropsの初期値を設定しておけば属性としてPropsが定義されていなくてもPropsが利用できる。

//コンポーネントの作成
function SampleComponent(props) {
  return (
    <div>
      props1 : {props.PropsName1}
      props2 : {props.PropsName2}
    </div>
  )
};
//defaultPropsの定義
SampleComponent.defaultProps = {
  PropsName1 : 'AAA',
  PropsName2 : 'BBB'
}
//コンポーネントの描画
ReactDOM.render(
  <SampleComponent/>,
  document.getElementById('root')
);

Stateの使い方
Stateはコンポーネント利用時に設定ができる値で、Propsと違い後から変更できる。

使い方はコンポーネント作成時にconstructorメソッド内でthis.stateオブジェクトに値を指定しておくことで他のメソッドからthis.stateとして取得することができる。

//コンポーネントの作成
class SampleComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      myState1 : 'aaa',
      myState2 : 'bbb'
    };
  }
  render() {
    return (
      <div>
        State1 : {this.state.myState1}
        State2 : {this.state.myState2}
      </div>
    )
  }
};
 //コンポーネントの描画
ReactDOM.render(
  <SampleComponent />,
  document.getElementById('root')
);

Stateを更新する場合はsetStateメソッドを使う。
setStateメソッドが実行されると即座にコンポーネントが再描画されHTMLに反映される。
以下のサンプルでは1秒毎にStateを更新し再描画を行なっている。

//コンポーネントの作成
class SampleComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      myState : 1
    };
    //1秒ごとにStateを更新する
    setInterval(()=>{
      this.setState({
        myState : this.state.myState + 1
      });
    },1000);
  }
  render() {
    return (
      <div>
        State : {this.state.myState}
      </div>
    )
  }
};
 //コンポーネントの描画
ReactDOM.render(
  <SampleComponent/>,
  document.getElementById('root')
);

UI変更に不要なプロパティはStateではなくPropsで管理すること。


↓参考サイト様
React入門 - to-R Media
React における State と Props の違い

【React】Reactの基礎知識を学習した①(JSX/Babel/コンポーネント)

Reactの環境構築とデプロイの方法までは理解できたのでいざコーディングを開始しようと思ったのだが想像以上にわからないことだらけだった。

心を入れ替えて基礎から学習したのでメモ。


JSXとは
JavaScript内に書ける特殊なルールのHTMLみたいなもの

<script type="text/babel">
ReactDOM.render(
    <h1>Hello, world!</h1>,
    document.getElementById('root')
);
</script>

rootにh1タグでHelloWorldを表示するだけのコード。
上記コードの<h1>Hello, world!</h1>の部分がJSXの構文。


Babelとは
様々なコードをブラウザが解釈できるJavaScriptに変換してくれるツール。
JSXの構文はそのままではJavaScriptの文法として不正なのでエラーとなるが、babel/browser.min.jsというツールを使ってブラウザ上でHTMLに変化されている。
script要素のtype属性にtext/babelと記述して使用する。

<script type="text/babel">
// Reactの命令
</script>

例えば先ほどのHello,world!のコードは以下のように変換される。

ReactDOM.render(
    React.createElement("h1", null, "Hello, world!"),
    document.getElementById('app')
);

注意点として、JSXの変換コストは軽くないためファイルサイズが大きくなる場合はあらかじめ変換しておいたJSファイルを使うのが一般的らしい。


コンポーネントとは
Reactでは作成したいUIを大きなコンポーネント(部品)として扱い、大きなコンポーネントは小さなコンポーネントの組み合わせで作成する。

コンポーネントの作成方法は複数あり

  • React.createClassのrenderメソッドを使う
  • React.Componentを継承する
  • function構文を使う(Stateless Functionsと呼ばれる)

※React 15.5.0以降、React.createClassは廃止予定とのこと。代わりにnpmモジュール「create-react-class」を使用する。使い方は割愛。

React.createClassを使う場合

//コンポーネントの作成//
var SampleComponent = React.createClass({
  render: function() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>texttext</h2>
      </div>
    )
  }
});
//コンポーネントの描画
ReactDOM.render(
  <SampleComponent />,
  document.getElementById('root')
);

SampleComponentというコンポーネントを作成してJSX内で<SampleComponent />タグとして利用している。

次にReact.Componentを継承して作成する場合

//コンポーネントの作成
class SampleComponent extends React.Component {
  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>texttext</h2>
      </div>
    )
  }
};
//コンポーネントの描画
ReactDOM.render(
  <SampleComponent />,
  document.getElementById('root')
);

あまり違いがわからないがReact.ComponentはES2015で定義されたClass構文を用いているため古いブラウザでは動作しないこともあるらしい。

最後にfunction構文で作成する場合

//コンポーネントの作成
function SampleComponent() {
  return (
    <div>
      <h1>Hello, world!</h1>
      <h2>Sample Text</h2>
    </div>
  )
};
//コンポーネントの描画
ReactDOM.render(
  <SampleComponent />,
  document.getElementById('root')
);

コンポーネント作成時は基本的にこの方法(Stateless Functions)を使う。
React.Componentで作成したコンポーネントと比較するとライフサイクルメソッド(後述)などの一部機能が簡略化されているので、必要に応じてReact.Componentと使い分けていく模様。

作成したコンポーネントは以下のように組み合わせて使うことができる。

//コンポーネントの作成
function MyH1() {
  return (
    <h1>Hello, world!</h1>
  )
}
function MyH2() {
  return (
    <h2>texttext</h2>
  )
}
function SampleComponent() {
  return (
    <div>
      <myH1 />
      <myH2 />
    </div>
  )
};
//コンポーネントの描画
ReactDOM.render(
  <SampleComponent />,
  document.getElementById('root')
);

長くなりそうなので続きはまた明日
サンプルコード等、参考サイト様のまるパクリだけど大丈夫だろうか。
怒られたら修正します。ごめんなさい。

↓参考サイト様
React入門 - to-R Media

【React】Firebaseでデプロイしてみる

f:id:hitoto28:20180916041429p:plain
Firebaseを使えばある程度は無料でWEBアプリを公開できる。
とりあえずデプロイできたのでログを残しておく。

1、デプロイしたいアプリのディレクトリに移動する

$ pwd
$ /Users/hitoto28/projects/ReactTest/helloworld

2、npmでfirebaseのパッケージをインストールする

$ npm install firebase --save

3、firebaseでデプロイする為に必要なjsファイルを作成する

$ mkdir firebase
$ touch firebase/config.js
$ touch firebase/index.js

4、各ファイルに以下のコードを記述する

↓ index.js

import firebase from 'firebase';
import { firebaseConfig } from './firebase/config.js';

export const firebaseApp = firebase.initializeApp(firebaseConfig);
export const firebaseDb = firebaseApp.database();

↓ config.js

export const firebaseConfig = {
  apiKey: "****************",
  authDomain: "****************",
  databaseURL: "****************",
  storageBucket: "****************",
  messagingSenderId: "****************"
};

✳︎✳︎✳︎の箇所にはfirebaseコンソールで作成されたAPIキー等を記述する(後述)

5、webブラウザでfirebase(https://console.firebase.google.com/)にログインし、適当なプロジェクトを作成する
※firebaseのログイン方法およびプロジェクト作成については簡単なので省略

6、プロジェクト画面を開きWEBアプリ用アイコンをクリックする
f:id:hitoto28:20180916025742p:plain

7、APIキー等の情報が表示されるので、赤枠の部分を先ほど作成したfirebase/config.jsにコピペする
f:id:hitoto28:20180916030258p:plain

8、デプロイに必要なツールをインストールする為、ターミナルで以下のコマンドを実行

$ npm install -g firebase-tools

9、インストールが成功したらfirebaseにログインする

$ firebase login

firebaseが情報を収集することに許可を求められるのでyesを入力するとブラウザでリンクが開かれる

? Allow Firebase to collect anonymous CLI usage and error reporting information?
 Yes

リンク先でGoogleアカウントを選択してログインする
以下の画面が表示されたら成功。ウィンドウは閉じて良い。
ウーホー!
f:id:hitoto28:20180916031928p:plain

10、firebaseを初期化する

$ firebase init

かっこいいけど読めない文字が表示される。FIREBASE?
f:id:hitoto28:20180916032856p:plain

11、セットアップ方法について聞かれるので今回は一番上のDatabaseのみ選択してエンターキーを押下する
f:id:hitoto28:20180916033434p:plain
操作方法はキーボードにて
矢印キーでカーソル移動
スペースキーで選択
エンターキーで決定

12、使用するプロジェクトを聞かれるのでfirebase管理画面で作成したプロジェクトを選択する
f:id:hitoto28:20180916033931p:plain

13、データベースのルール設定をどのファイルで行うか聞かれるのでそのままエンターキーを押下するf:id:hitoto28:20180916034230p:plain

14、アプリ内にfirebase.jsonとdatabase.rules.jsonが作成されていることを確認し、それぞれ以下のように編集する。

↓ firebase.json

{
  "database": {
    "rules": "database.rules.json"
  },
  "hosting": {
    "public": "build"
  }
}

↓ database.rules.json

{
  "rules": {
    ".read": "true",
    ".write": "true"
  }
}

15、編集が完了したらターミナルでビルド実行

$ npm run build

16、ビルドが問題なく完了したらデプロイする

$ firebase deploy

デプロイが完了するとHosting URLが表示されるので、ブラウザで開く
f:id:hitoto28:20180916040357p:plain

アプリの画面が表示されたら成功


↓参考サイト様
React & Firebaseで簡単なChatアプリを作ってみた
Reactで作成したアプリをfirebaseでデプロイする方法 - 28歳からはじめるフリーランスLIFE!

【Linux】ログファイルへの追記を監視する

最近よく使うのでメモ

xxxxx.logの追記状況を監視

$ tail -f xxxxx.log

半角スペースで複数指定することもできるらしい(未確認)

$ tail -f /etc/file1 /etc/file2

ワイルドカードも使えるらしい(未確認)

$ tail -f *.log


参考サイト様
tailコマンドについて詳しくまとめました 【Linuxコマンド集】

ペンギンハイウェイを観てきた

f:id:hitoto28:20180912045038j:plain
とても面白かった。
自分の中での2018ベスト映画はシェイプ・オブ・ウォーターだったのだけれど、ペンギンハイウェイも候補にしたい。
脚本・構成・音楽・アニメーションの美しさ・魅力的なキャラクター、エンタメ映画としても最高だったし考察要素も多く含まれておりコアな映画ファンにも楽しめる内容だったと思う。

何よりも感銘を受けたのは、主人公アオヤマ君の研究に対する姿勢である。

常に研究のことを考え世界の果てを知ろうとするそのマインド。
同級生に煽られようが理不尽な妨害を受けようが決して感情的にならず己の成すべきことを成そうとするその姿は研究者の鑑そのものだ。

ウチダ君になぜ怒らないのかを問われた際の「感情的になりそうな時はオッパイのことを考えるようにしている」というセリフ(正解なセリフは忘れた)は私の座右の銘にしようと思う。

私は汚らしい大人なので本当にオッパイのことを考えるとそれはそれで暴走しかねないので、オッパイの部分を研究に置き換えて記憶しておこうと思う。

それから、アオヤマ君の師であるお父さんの教えも素晴らしかった。

・問題解決のコツは物事を小さく分解して考えること
・つまづいた時はメモを1枚の紙にまとめてパズルを解くように思考する
・どうしてもわからない時は考えるのをやめる

うろ覚えだがこんな感じだったはず。

私も仕事でハマった時はだいたいこの3パターンのどれかで解決することが多い気がする。

とにかく、エンジニア的な視点で鑑賞するとなんだか色々と得るものの多い映画だった。

円盤が出たら買おう。