React

はじめてのReact #16「Componentの連携」子要素にアクセスする

これまでは、最終的にrender()する際には<Foo />のようにタグで何らかの文字列や要素を囲わない状態でした。今回はそこから一歩進んで<Foo>Hello!</Foo>のように何らかの要素を挟んでみたいと思います。

ダイアログ Component

おもしろサンプルが思いつかなかったので、公式ドキュメントほぼそのまま、ダイアログの作成を行います。

サンプル

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8" />
  <title>Dialog</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>

  <!-- Don't use this in production: -->
  <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
</head>
<body>

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

<script type="text/babel">
class Dialog extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (
      <div style={{backgroundColor:'lightpink', width:'500px', border:'5px solid red'}}>
        {this.props.children}
      </div>
    );
  }
}

ReactDOM.render(
  <Dialog>
    <h1>Hello! World</h1>
    nice to meet you!
  </Dialog>,
  document.getElementById('root')
);
</script>
</body>
</html>

続きを読む

はじめてのReact #15「Componentの連携」複数同時に処理をする

いよいよReactの真骨頂っぽいところに足を突っ込んでみます。前回はComponentの中にComponentが1つだけ内包されていましたが、これを複数にしてみたいと思います。

西暦・和暦 相互変換Component

今年の5月には新しい年号が爆誕するのにちなんで、西暦と和暦を相互に変換するComponentを作成してみたいと思います。今回も公式ドキュメントのサンプルを改変した物になります。

実行すると昭和、平成、西暦の3つのテキストボックスが表示されます。いずれか1つに入力すると残りの2つが連動して変化します。コードがちょっと長いのですが、理解のしやすさを優先しただけで実際にやってることは大したことありません。

サンプル

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8" />
  <title>HeiseiConvert</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>

  <!-- Don't use this in production: -->
  <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
</head>
<body>

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

<script type="text/babel">
class YearInput extends React.Component {
  constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(e) {
    this.props.onYearChange(e.target.value);
  }

  render() {
    const year = this.props.year;
    const type = this.props.type;

    return (
      <fieldset>
        <legend>{type}:</legend>
        <input value={year}
               placeholder={this.props.placeholder}
               onChange={this.handleChange} /> 
               年
      </fieldset>
    );
  }
}

class HeiseiConvert extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
          ad: "",
       showa: "",
      heisei: ""
    };

    this.handleAdChange     = this.handleAdChange.bind(this);
    this.handleShowaChange  = this.handleShowaChange.bind(this);
    this.handleHeiseiChange = this.handleHeiseiChange.bind(this);
  }

  handleAdChange(year) {
    this.setState({
          ad: year,
       showa: this.toConvert(year, -1925),
      heisei: this.toConvert(year, -1989)
    });
  }

  handleShowaChange(year) {
    this.setState({
          ad: this.toConvert(year, 1925),
       showa: year,
      heisei: this.toConvert(year, -63)
    });
  }

  handleHeiseiChange(year) {
    this.setState({
          ad: this.toConvert(year, 1988),
       showa: this.toConvert(year, 63),
      heisei: year
    });
  }

  toConvert(year, value){
    if( Number.isNaN(parseFloat(year)) ){
      return('');
    }
    return( Number(year) + value);
  }

  render() {
    return (
      <div>
        <YearInput
          type="昭和"
          placeholder="例: 64"
          year={this.state.showa}
          onYearChange={this.handleShowaChange} />
        <YearInput
          type="平成"
          placeholder="例: 30"
          year={this.state.heisei}
          onYearChange={this.handleHeiseiChange} />
        <YearInput
          type="西暦"
          placeholder="例: 2019"
          year={this.state.ad}
          onYearChange={this.handleAdChange} />
      </div>
    );
  }
}

ReactDOM.render(
  <HeiseiConvert />,
  document.getElementById('root')
);
</script>
</body>
</html>

続きを読む

はじめてのReact #14「Componentの連携」入力された値を動的に渡す

今回はユーザーが入力した値を別のComponentにリアルタイムに渡すサンプルを作ってみたいと思います。

カラーチェッカーComponent

テキストボックスに色の名前を入力すると、ほぼリアルタイムに■の色が変化するComponentになります。Reactの公式ドキュメントの水の温度によって表示を変化させるサンプルを改変した物です。

サンプル

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8" />
  <title>ColorChecker</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>

  <!-- Don't use this in production: -->
  <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
</head>
<body>

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

<script type="text/babel">
function ShowColor(props) {
  return(
    <p style={{color:props.color, fontSize:'20px'}}>■</p>
  );
}

class ColorChecker extends React.Component {
  constructor(props) {
    super(props);
    this.state = {color: ''};

    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(e) {
    this.setState({color: e.target.value});
  }

  render() {
    const color = this.state.color;
    return (
      <fieldset>
        <legend>色名を入力してください:</legend>
        <input
          value={color}
          onChange={this.handleChange}
          placeholder="例:Red" />

        <ShowColor color={color} />
      </fieldset>
    );
  }
}

ReactDOM.render(
  <ColorChecker />,
  document.getElementById('root')
);
</script>
</body>
</html>

続きを読む

はじめてのReact #13「フォームと連動する」ラジオボタン編

Reactでフォームを使ってみようシリーズも佳境に差し迫った第4弾。今回はラジオボタンを触ってみます。

時限爆弾の解体ラジオボタンComponent

もはら映画で定番となった、時限爆弾の解体シーンで「青と赤どちらのコードを切るか…」を再現するComponentを作ってみたいと思います。3色のラジオボタンが並んでおりハズレを選択(コードを切断)すると爆発します。

サンプル

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8" />
  <title>BomButton</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>

  <!-- Don't use this in production: -->
  <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
</head>
<body>

<h1>BomButton</h1>
<p>線を一つ選んで爆弾を解除してください</p>
<img src="./bom1.png">
<div id="root"></div>

<script type="text/babel">
class BomButton extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      radio: [
        {cd:'red',   name:"赤", checked:false},
        {cd:'blue',  name:"青", checked:false},
        {cd:'green', name:"緑", checked:false}
      ],
      lastclick: null  //最後に選択された色を入れる
    };

    // State内の色の中から抽選を行う
    let i = Math.floor(Math.random() * 100) % this.state.radio.length;
    this.hit = this.state.radio[i].cd;

    // 爆発時の素材を事前ロードしておく
    this._preload();

    // イベント用メソッド
    this.handleRadioClick = this.handleRadioClick.bind(this);
  }

  /**
   * 爆発時の素材を事前ロード
   */
  _preload(){
    this.se = new Audio('./bomb1.mp3');
    this.se.load();

    let img = new Image();
    img.src = "./bakuhatsu.png";
  }

  /**
   * ラジオボタンをクリック
   */
  handleRadioClick(e) {
    if( ! confirm('本当にこの線で良いですか?') ){
      return(false);
    }

    let name  = e.target.name;
    let value = this.state.radio.map( (item)=>{
      return({
        cd: item.cd,
        name: item.name,
        checked: (item.cd===name)? true:false
      })
    });

    this.setState({
        radio: value
      , lastclick: name
    });
  }

  render() {
    //----------------
    // 当選したら爆発
    //----------------
    if( this.hit === this.state.lastclick ){
      this.se.play();
      return <div><img src="./bakuhatsu.png" /></div>
    }
    //----------------
    // 選択肢の表示
    //----------------
    else{
      const radio = this.state.radio;
      const listItems = radio.map((r) =>
        <label key={r.cd.toString()} style={{color: r.cd}}>
          <input
            type="radio"
            name={r.cd}
            value={r.cd}
            checked={r.checked}
            onChange={this.handleRadioClick} />
          {r.name}<br />
        </label>
      );
      return <form>{listItems}</form>
    }
  }
}

ReactDOM.render(
  <BomButton />,
  document.getElementById('root')
);
</script>
</body>
</html>

続きを読む

はじめてのReact #12「フォームと連動する」チェックボックス編

Reactでフォームを使ってみようシリーズも第3弾。今回のテーマはチェックボックスです。

都道府県チェックボックスComponent

よく見かける都道府県一覧のチェックボックスです。例えば「中国地方」をチェックすると、島根や鳥取など中国地方全体にチェックが入る機能もついてます。

サンプル

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8" />
  <title>AreaCheck</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>

  <!-- Don't use this in production: -->
  <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
</head>
<body>

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

<script type="text/babel">
  class AreaCheck extends React.Component {
    constructor(props) {
      super(props);
      this.cd = this.props.cd;
      this.state = {
        area: this.props.area
      };

      this.handleKenChange = this.handleKenChange.bind(this);  //各都道府県のチェック
      this.handleAllChange = this.handleAllChange.bind(this);  //まとめてチェック
    }

    /**
     * 各都道府県をチェック
     */
    handleKenChange(e) {
      let name  = e.target.name;
      let value = this.state.area.map( (ken)=>{
        return({
          cd: ken.cd,
          name: ken.name,
          checked: (ken.cd===name)? e.target.checked:ken.checked
        })
      });

      this.setState({area: value});
    }

    /**
     * まとめてチェック
     */
    handleAllChange(e){
      let value = this.state.area.map( (ken)=>{
        return({
          cd: ken.cd,
          name: ken.name,
          checked: e.target.checked
        })
      });

      this.setState({area: value});
    }

    render() {
      let area = this.state.area;
      let listItems = area.map((ken) =>
        <label key={ken.cd.toString()}>
          <input
            type="checkbox"
            name={ken.cd}
            value={ken.cd}
            checked={ken.checked}
            onChange={this.handleKenChange} />
            {ken.name}
        </label>
      );

      return (
        <form>
          <label key={this.cd}>
            <input type="checkbox" name="ALL" onChange={this.handleAllChange} />
            このエリアをチェック
          </label>
          <br />
          {listItems}
        </form>
      );
    }
  }

  const Chugoku = [
    {cd:'31', name:'鳥取県', checked:false},
    {cd:'32', name:'島根県', checked:false},
    {cd:'33', name:'岡山県', checked:false},
    {cd:'34', name:'広島県', checked:false},
    {cd:'35', name:'山口県', checked:false}
  ];
  const Shikoku =[
    {cd:'36', name:'徳島県', checked:false},
    {cd:'37', name:'香川県', checked:false},
    {cd:'38', name:'愛媛県', checked:false},
    {cd:'39', name:'高知県', checked:false}
  ];
  ReactDOM.render(
    <div>
      <AreaCheck cd="CG" area={Chugoku} />
      <AreaCheck cd="SK" area={Shikoku} />
    </div>,
    document.getElementById('root')
  );
</script>
</body>
</html>

続きを読む

はじめてのReact #11「フォームと連動する」プルダウン編

前回のテキストボックスに続き、今回はプルダウン(<select>)の操作方法になります。
ほぼ同じやり方で<ul>, <ol>などのリストにも適用できます。

メンバーリストComponent

メンバーの一覧をプルダウンとして表示し、名前をクリックすると削除されるComponentです。公式ドキュメントの「Lists and Keys」のサンプルコードを参考にしています。

サンプル

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8" />
  <title>MemberList</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>

  <!-- Don't use this in production: -->
  <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
</head>
<body>
  <div id="root"></div>

  <script type="text/babel">
   class MemberList extends React.Component {
     constructor(props) {
       super(props);
       this.state = {
          guys: props.guys
       };

       this.handleRemove = this.handleRemove.bind(this);
     }

     handleRemove(id){
       const guys = this.state.guys;
       const new_guys = [];

         for( let i=0; i<guys.length; i++ ){
           if(guys[i].id !== id){
             new_guys.push(guys[i]);
           }
       }

       this.setState({guys:new_guys});
     }

     render(){
       const guys = this.state.guys;
       const listItems = guys.map((guy) =>
         <option key={guy.id.toString()} onClick={ ()=>{ this.handleRemove(guy.id) } }>
           {guy.name}
         </option>
       );

       return <select size="3">{listItems}</select>;
     }
   }


    const guys = [
      {id:10, name:"Foo"},
      {id:20, name:"Bar"},
      {id:30, name:"Hoge"}
    ];

    ReactDOM.render(
      <MemberList guys={guys} />,
      document.getElementById('root')
    );
  </script>
</body>
</html>

続きを読む

はじめてのReact #10「フォームと連動する」テキストボックス編

10回目ともなるとだいぶReactで何かを作ることにも慣れてきましたねw 今回はいよいよフォームと関連した処理を書いてみたいと思います。Reactに限らずですがユーザーの入力とリアルタイムに連動して表示が切り替わるのは作っていて楽しいですよね。

入力候補を表示してくれるComponent

ユーザーが入力した文字に応じて、入力候補を自動的に表示してくれるComponentを作成します。今回も公式ドキュメントにあるサンプルコードを、編集して作成した物です。

サンプル

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8" />
  <title>AutoCompletionBox</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>

  <!-- Don't use this in production: -->
  <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
</head>
<body>
  <div id="root"></div>

  <script type="text/babel">
    class AutoCompletionBox extends React.Component {
      constructor(props) {
        super(props);
        this.INITIAL_WORD = '入力してください';

        this.state = {
          value: '',                 //ユーザーが入力した文字列が入る
          word: this.INITIAL_WORD    //自動補完用の文字列が入る
        };

        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
      }

      handleChange(e) {
        let buff = e.target.value;            //入力された文字列
        let ac   = this.candidateData(buff);  //自動補完された文字列

        this.setState({value: buff, word: ac});
      }
      handleSubmit(e) {
        // 初期文言と自動補完用の文字が異なっていればStateを更新
        if( this.state.word !== this.INITIAL_WORD ){
          this.setState({value: this.state.word});
        }
        e.preventDefault();  //Submitイベントによる画面遷移をキャンセル
      }

      /**
       * 自動補完用の文字列を返却
       */
      candidateData(key){
        let i = key.slice(0,1).toLowerCase();  //先頭の1文字を取り出し小文字に
        let data = {
          a: 'Android',
          b: 'BlackBerryOS',
          f: 'FireFoxOS',
          i: 'iOS',
          t: 'Tizen',
          u: 'Ubuntu Touch',
          w: 'Windows 10 Mobile'
        };

        return( ( i in data )?  data[i]:this.INITIAL_WORD );
      }

      render() {
        return (
          <form onSubmit={this.handleSubmit}>
            <label>
              お使いのスマートフォンのOSは?<br />
              <input type="text" value={this.state.value} onChange={this.handleChange} /><br />
              <input type="submit" value={this.state.word} />
            </label>
          </form>
        );
      }
    }

    ReactDOM.render(
      <AutoCompletionBox />,
      document.getElementById('root')
    );
  </script>
</body>
</html>

続きを読む

はじめてのReact #9「状態に合わせてComponentを切り替える」

Componentの状態をthis.setState()で変化させる度にrender()が自動的に実行され最新の描画がされるのですが、Reactでは単純なHTMLだけではなくComponent自体を別の物に切り替えることができます。

今回はReactの公式ドキュメント「Conditional Rendering」を単純化したサンプルコードでお送りしします。

ログインComponent

よくあるログインとログアウトの管理用のComponentをイメージしたサンプルになっています。最初はログインしていない状態ですが、ボタンをクリックすることでログイン状態になります。再度ボタンをクリックすると最初の状態(ログアウト)に戻るというシンプルなものです。

サンプル

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8" />
  <title>LoginControl</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>

  <!-- Don't use this in production: -->
  <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
</head>
<body>
  <div id="root"></div>

  <script type="text/babel">
    class LoginControl extends React.Component {
      constructor(props) {
        super(props);

        this.handleLoginClick  = this.handleLoginClick.bind(this);
        this.handleLogoutClick = this.handleLogoutClick.bind(this);

        this.state = {
          isLoggedIn: false
        };
      }

      handleLoginClick() {
        this.setState({isLoggedIn: true});
      }
      handleLogoutClick() {
        this.setState({isLoggedIn: false});
      }

      render() {
        const isLoggedIn = this.state.isLoggedIn;
        let message;
        let button;

        if (isLoggedIn) {
          message = "ナイス、ログイン";
          button  = <LogoutButton onClick={this.handleLogoutClick} />;
        }
        else {
          message = "ログインしてください";
          button  = <LoginButton onClick={this.handleLoginClick} />;
        }

        return (
          <div>
            <h1>{message}</h1>
            {button}
          </div>
        );
      }
    }

    function LogoutButton(props) {
      return <button onClick={props.onClick}>ログアウト</button>;
    }

    function LoginButton(props) {
      return <button onClick={props.onClick}>ログイン</button>;
    }

    ReactDOM.render(
      <LoginControl />,
      document.getElementById('root')
    );
  </script>
</body>
</html>

続きを読む

はじめてのReact #8「イベント処理を試してみよう」

イベント処理は、タグ内にonClickなどのイベントハンドラ用の属性を指定することで定義できます。

これだけ聞くと正直気持ち悪いですよねw 結論から言うと最終的には問題ない形でレンダリングされます。実際のサンプルコードを元に話を進めていきましょう。

おみくじComponent

今回はボタンをクリックすると、運勢がアラートされる簡単な「おみくじ」を作成してみたいと思います。

サンプル

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8" />
  <title>おみくじ</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>

  <!-- Don't use this in production: -->
  <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
</head>
<body>
  <div id="root"></div>

  <script type="text/babel">
    class Omikuji extends React.Component {
      dropOmikuji(e){
        let unsei = ["大吉", "吉", "中吉", "小吉", "凶", "大凶"];
        let i = Math.ceil(Math.random() * 100) % unsei.length;

        alert(`あなたの運勢は${unsei[i]}です`);  // ``内に ${} で変数を埋め込めるのはES2015からの追加仕様
      }

      render() {
        return <button onClick={this.dropOmikuji}>おみくじを引く</button>;
      }
    }

    ReactDOM.render(
      <Omikuji />,
      document.getElementById('root')
    );
  </script>
</body>
</html>

続きを読む

はじめてのReact #7「Propsのデフォルト値を設定しよう」

Props未指定の場合のデフォルト値の設定を行う場合に、便利な機能が用意されています。前回行ったデータ型の定義と同様に、連想配列(ハッシュ)を書いてあげるだけで実現できます。

コンストラクタでやれば良くね?というツッコミもありそうですがw Props未指定時に固定値を入れるだけのシンプルなケースの場合はスッキリかけるので便利だったりします。あとは決められた箇所にまとまっているとメンテナンス性も上がりますしね。

指定日までの日数を表示するComponent その3

前回のソースコードに、Propsのデフォルト値を設定するコードを追加しました。今回もこの機能はReact本体には含まれていないためライブラリ「prop-types」を追加している点にも注意してください。

これまでは以下のようにmessage属性を指定していましたが、今回はわざとこれを外しています。

ReactDOM.render(
  <RemainTime date="2112-09-03 00:00:00" message="ドラえもん誕生" />,
  document.getElementById('root')
);

サンプル

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8" />
  <title>RemainTime</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/prop-types@15.6/prop-types.js"></script>

  <!-- Don't use this in production: -->
  <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
</head>
<body>
  <div id="root"></div>

  <script type="text/babel">
    class RemainTime extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          now: new Date().getTime(),
          target: new Date(props.date).getTime()
        };
      }

      render() {
        let remain = Math.floor( ( this.state.target - this.state.now ) / (1000 * 60 * 60 * 24) );
        return <h1>{this.props.message}まで約{remain}日</h1>;
      }
    }

    /**
     * Propsの型定義
     */
    RemainTime.propTypes = {
         date: PropTypes.string,
      message: PropTypes.string
    };

    /**
     * Propsのデフォルト値
     */
    RemainTime.defaultProps = {
      message: "Xデー"
    };

    ReactDOM.render(
      <RemainTime date="2112-09-03 00:00:00" />,
      document.getElementById('root')
    );
  </script>
</body>
</html>

続きを読む

はじめてのReact #6「Propsのデータ型をチェックしよう」

大規模なプロジェクトでは必須?

ComponentがどのようなPropsを欲しがっているか、プロジェクトの規模が大きくなればなるほど管理が大変になってきます。そこでReactではPropsのデータ型を定義できる機能を提供しています。

指定日までの日数を表示するComponent その2

前回のソースコードに、Propsの型を定義するコードを追加しました。また型定義の機能はReact本体には含まれていないため新しくライブラリ「prop-types」を追加している点にも注意してください。

ここではわざと型定義に反するようなPropsの渡し方をして、どのような挙動になるかを確認してみます。

サンプル

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8" />
  <title>RemainTime</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/prop-types@15.6/prop-types.js"></script>

  <!-- Don't use this in production: -->
  <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
</head>
<body>
  <div id="root"></div>

  <script type="text/babel">
    class RemainTime extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          now: new Date().getTime(),
          target: new Date(props.date).getTime()
        };
      }

      render() {
        let remain = Math.floor( ( this.state.target - this.state.now ) / (1000 * 60 * 60 * 24) );
        return <h1>{this.props.message}まで約{remain}日</h1>;
      }
    }

    /**
     * Propsの型定義
     */
    RemainTime.propTypes = {
         date: PropTypes.string,
      message: PropTypes.string
    };

    ReactDOM.render(
      //わざとmessageを文字列ではなく、配列として渡してみます
      <RemainTime date="2112-09-03 00:00:00" message={["ドラえもん誕生"]} />,
      document.getElementById('root')
    );
  </script>
</body>
</html>

続きを読む

はじめてのReact #5「Propsを使おう」

Componentに引数を渡せるProps

これまでのサンプルでは以下のように単にタグを書くことでComponentを実行していました。これだけでも十分なパワーを持っているのですが、より汎用的なComponentにすべきPropsと呼ばれる機能を使うと、Component内部に引数を渡すことができます。

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

指定日までの日数を表示するComponent

今回は指定した日付まで、残り何日か表示してくれるComponentを作成してみます。Props部分に集中したかったのでカウントダウン的な処理は端折りましたw

サンプル

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8" />
  <title>RemainTime</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>

  <!-- Don't use this in production: -->
  <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
</head>
<body>
  <div id="root"></div>

  <script type="text/babel">
    class RemainTime extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          now: new Date().getTime(),
          target: new Date(props.date).getTime()
        };
      }

      render() {
        let remain = Math.floor( ( this.state.target - this.state.now ) / (1000 * 60 * 60 * 24) );
        return <h1>{this.props.message}まで約{remain}日</h1>;
      }
    }

    ReactDOM.render(
      <RemainTime date="2112-09-03 00:00:00" message="ドラえもん誕生"/>,
      document.getElementById('root')
    );
  </script>
</body>
</html>

続きを読む

はじめてのReact #4「Lifecycleを活用してみる」

ComponentのLifecycle

ReactのComponentは生まれてから死ぬ(破棄される)までの間にたくさんのイベントが用意されており、それらのタイミングで特定のメソッドを実行してくれる機能を自由に使用することができます。

現在時間を表示するComponent その3

今回はReactの公式ドキュメントのソースを参考にしながら、前回まで作成してきたJustnowComponentを時間が経過するごとに表示も変更するようにしてみたいと思います。

サンプル

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8" />
  <title>Justnow3</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>

  <!-- Don't use this in production: -->
  <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
</head>
<body>
  <div id="root"></div>

  <script type="text/babel">
    class Justnow extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          now: new Date()
        };
      }

     /**
      * Lifecycle: ComponentがDOMツリーに加わった際の処理
      */
      componentDidMount() {
        this.timerID = setInterval(
          () => this.tick(),
          1000
        );
      }

     /**
      * Lifecycle: ComponentがDOMツリーから削除される際の処理
      */
      componentWillUnmount() {
        clearInterval(this.timerID);
      }

      tick() {
        this.setState({
          now: new Date()
        });
      }

      render() {
        let now = this.state.now;
        let now_date = [now.getFullYear(), now.getMonth()+1, now.getDate()].join('-');
        let now_time = [now.getHours(), now.getMinutes(), now.getSeconds()].join(':');

        return <h1>{now_date} {now_time}</h1>;
      }
    }

    ReactDOM.render(
      <Justnow />,
      document.getElementById('root')
    );
  </script>
</body>
</html>

以下のページにあるサンプルコードを参考にしています。

続きを読む

はじめてのReact #3「Stateを試してみる」

Component内部のデータ管理をどうするか

Reactの売りはデータに変更が発生すると、それに連動しrender()メソッドが実行されるところでもあります。勝手にデータが書き換わってくれる、しかも高速に! ところが前回作成したJustnow Componentではそういった動きになってくれません。

今回はまずはComponent内部でどのようにデータを持つべきかを試してみたいと思います。

現在時間を表示するComponent その2

Reactでは内部でデータを保持するためにstateというプロパティに値を格納します。
前回はrender()メソッド内に持っていたデータを、今回はstateに移し替えてみます。

サンプル

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8" />
  <title>Justnow2</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>

  <!-- Don't use this in production: -->
  <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
</head>
<body>
  <div id="root"></div>

  <script type="text/babel">
    class Justnow extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          now: new Date()
        };
      }

      render() {
        let now = this.state.now;
        let now_date = [now.getFullYear(), now.getMonth()+1, now.getDate()].join('-');
        let now_time = [now.getHours(), now.getMinutes(), now.getSeconds()].join(':');

        return <h1>{now_date} {now_time}</h1>;
      }
    }

    ReactDOM.render(
      <Justnow />,
      document.getElementById('root')
    );
  </script>
</body>
</html>

続きを読む

はじめてのReact #2「Componentを試してみる」

ReactはComponentを作るための仕組み?

Reactを触っていて感じるのは、React自体はコンポーネントを作るための仕組みなんだなということです。

例えば現在時間を表示する機能がほしいと思ったら <Justnow>というオリジナルのタグをReactで作成し、必要なWebページに埋め込むだけ。もちろん要素名(タグ名)は自由に命名できます。あとはこの応用で機能毎に必要な要素を用意して組み合わせるようなイメージでしょうか。Reactというと色々できて難しそうなイメージがありましたが、スタート地点は非常にシンプルな気がします。

今回は先ほど例に出した現在時間を表示するためのJustnow Componentを作ってみたいと思います。

現在時間を表示するComponent

サンプル

前回のサンプルにちょろっと書き足しました。このままコピペしてブラウザで開けば実行されます。

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8" />
  <title>Justnow</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>

  <!-- Don't use this in production: -->
  <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
</head>
<body>
  <div id="root"></div>

  <script type="text/babel">
    class Justnow extends React.Component {
      render() {
        let now = new Date();
        let now_date = [now.getFullYear(), now.getMonth()+1, now.getDate()].join('-');
        let now_time = [now.getHours(), now.getMinutes(), now.getSeconds()].join(':');

        return <h1>{now_date} {now_time}</h1>;
      }
    }

    ReactDOM.render(
      <Justnow />,
      document.getElementById('root')
    );
  </script>
</body>
</html>

続きを読む