クモのようにコツコツと

フロントエンドエンジニア イイダリョウの技術ブログ。略称「クモコツ」

【React】ステートで制御構造(条件分岐、ループ)

Reactの続きです。前回はステートでsetState()、タイマー処理、イベント処理をやってみました。今回は三項演算子による条件分岐と、map()によるループをやってみます。それではいきましょう!

【目次】

※参考:前回記事
【React】Reactプロジェクトでステートを事始め(setState()、タイマー処理、イベント処理) - クモのようにコツコツと

※参考:Reactを習得するためにやったことまとめ
qiita.com

前回のおさらい

今回も掌田さんの「React.js & Next.js入門」を参考に進める。

React.js & Next.js超入門

React.js & Next.js超入門

前回作ったもの f:id:idr_zz:20200527072303j:plain

  • stateでステートの初期値を設定
  • setState()でステートの値の更新設定(カウントアップ)
  • onClickでクリックイベントによるステート更新を実行

詳細は前回記事を参照

※参考:前回記事
【React】Reactプロジェクトでステートを事始め(setState()、タイマー処理、イベント処理) - クモのようにコツコツと

今回はさらに条件分岐やループなどの制御構造をやってみる。

条件分岐(三項演算子)

まずは条件分岐から。

作ってみたもの

初期値で太郎が「羊が何匹??」と聞いている。 f:id:idr_zz:20200601191013j:plain 「数える」を押すと

次郎が「羊が1匹!」と答える。
f:id:idr_zz:20200601191016j:plain 「数える」を押すと

太郎が「羊が2匹?」と聞く。
f:id:idr_zz:20200601191020j:plain 「数える」を押すと

次郎が「羊が3匹!」と答える
f:id:idr_zz:20200601191025j:plain 以下、交互に繰り返す。

以前、JSXで行った条件分岐はこちらを参照。この中の「三項演算子」を使った条件分岐を使っている。

※参考:【React】条件分岐の書き方(if文エラー回避、論理演算子、三項演算子) - クモのようにコツコツと

Appコンポーネントの変更内容

まずAppコンポーネントにflagキーを追加する。初期値はtrue

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      msg1: "羊が",
      num: 1,
      msg2: "匹",
      message:  "羊が何匹?",
      flag: true // 追記
    };
    this.countUp = this.countUp.bind(this);
  }

countUp()メソッドの変更内容

countUp()メソッドでflagの変更を追記する。

  countUp(e) {
    this.setState((state) => ({
      num: state.num +1,
      message: state.msg1 + state.num + state.msg2,
      flag: !state.flag // 追記
    }));
  }

state.flagの値を反対!にするという設定。

これでtruefalseに、逆にfalsetrueになる。

render()に三項演算子を追加

最後にJSXレンダリングのrender()に三項演算子を追加

  render() {
    return <div className="App">
      <header className="App-header">
        <div className="App-images">
          <Img align="left" />
          <Img align="center" />
          <Img align="rignt" />
        </div>
        <h1>初めてのステート</h1>
        {this.state.flag ?
        <p>太郎「{this.state.message}?」</p>
        :
        <p>次郎「{this.state.message}!」</p>
        }
        <button onClick={this.countUp}>数える!</button>
      </header>
    </div>
  }

h1タグの下、flagtrueだったら太郎が「○○?」という。falseだったら次郎が「○○!」という。

App.js全体

import React from 'react';
import Img from './Img';
import './App.css';

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      msg1: "羊が",
      num: 1,
      msg2: "匹",
      message:  "羊が何匹?",
      flag: true
    };
    this.countUp = this.countUp.bind(this);
  }

  countUp(e) {
    this.setState((state) => ({
      num: state.num +1,
      message: state.msg1 + state.num + state.msg2,
      flag: !state.flag
    }));
  }


  render() {
    return <div className="App">
      <header className="App-header">
        <div className="App-images">
          <Img align="left" />
          <Img align="center" />
          <Img align="rignt" />
        </div>
        <h1>初めてのステート</h1>
        {this.state.flag ?
        <p>太郎「{this.state.message}?」</p>
        :
        <p>次郎「{this.state.message}!」</p>
        }
        <button onClick={this.countUp}>数える!</button>
      </header>
    </div>
  }
}

export default App;

ループ(map())

次にループをやってみる。

作ってみたもの

「初めてのステート」の下に「はっぴいえんど」 f:id:idr_zz:20200601193552j:plain

はっぴいえんどのファーストの曲目。この部分をループで表示している。 f:id:idr_zz:20200601193556j:plain

以前、JSXで行ったループはこちら。この中のmap()メソッドを使っている。

※参考:【React】ループの書き方(for文エラー回避、配列、map()) - クモのようにコツコツと

Appコンポーネントの変更内容

配列song

まずAppコンポーネントにループで表示したい曲名を配列song`に入れる

class App extends React.Component {
  song = [
    '抱きしめたい',
    '空いろのくれよん',
    '風をあつめて',
    '暗闇坂むささび変化',
    'はいからはくち',
    'はいから・びゅーちふる',
    '夏なんです',
    '花いちもんめ',
    'あしたてんきになあれ',
    '颱風',
    '春らんまん',
    '愛餓を'
  ];
コンストラクタ

次にコンストラクタでステートを設定

  constructor(props) {
    super(props);
    this.state = {
      list:this.song
    };
  }

listキーに配列songをセット

JSX設定

render()でレンダリングするJSXを設定。

  render() {
    return <div className="App">
      <header className="App-header">
        <div className="App-images">
          <Img align="left" />
          <Img align="center" />
          <Img align="rignt" />
        </div>
        <h1>初めてのステート</h1>
        <h2>はっぴいえんど</h2>
        <List title="はっぴいえんど(1970)" song={this.song} />
      </header>
    </div>
  }
}
  • h2タグの下で後述するListコンポーネントを読み込む
  • Listtitle属性は文字列、song属性はsong

Listコンポーネント:map()でループ実行

Appコンポーネントで読み込むListコンポーネントを作成

class List extends Component {
  number = 1;

  render () {
    let song = this.props.song;
    return (
      <div>
        <p>{ this.props.title }</p>
        <ul>
          {song.map((item) =>
            <Item number={this.number++} value={item} key={this.number} />
          )}
        </ul>
      </div>
    );
  }
}
  • グローバル変数numberを設定。初期値は1
  • render ()でJSXを設定
  • 変数songpropsの配列songを設定
  • pタグはpropstitle
  • ulタグの中身:配列songの値をmap()メソッドでループ
  • map()の引数は無名関数で、無名関数の引数はitem
  • 無名関数の処理:後述するItemコンポーネントを読み込む
  • Itemnumber属性はnumberを1つ加算、value属性はitemkey属性はnumber

Itemコンポーネント作成

Listコンポーネントで読み込むItemコンポーネントを作成

  class Item extends Component {
    liStyle = {
      listStyleType: "none",
      textAlign: "left"
    };

    render () {
      return (
      <li style={this.liStyle}>{this.props.number}. {this.props.value}</li>
      );
    }
  }
  • グローバル変数liStyleの値は連想配列でCSSスタイル
  • render()でJSXを設定
  • liタグの中にstyle属性があり値はliStyle
  • liタグの中身はpropsnumberpropsvalue

App.js全体

import React, { Component } from 'react';
import Img from './Img';
import './App.css';

class App extends React.Component {
  song = [
    '抱きしめたい',
    '空いろのくれよん',
    '風をあつめて',
    '暗闇坂むささび変化',
    'はいからはくち',
    'はいから・びゅーちふる',
    '夏なんです',
    '花いちもんめ',
    'あしたてんきになあれ',
    '颱風',
    '春らんまん',
    '愛餓を'
  ];

  constructor(props) {
    super(props);
    this.state = {
      list:this.song
    };
  }

  render() {
    return <div className="App">
      <header className="App-header">
        <div className="App-images">
          <Img align="left" />
          <Img align="center" />
          <Img align="rignt" />
        </div>
        <h1>初めてのステート</h1>
        <h2>はっぴいえんど</h2>
        <List title="はっぴいえんど(1970)" song={this.song} />
      </header>
    </div>
  }
}

class List extends Component {
  number = 1;

  render () {
    let song = this.props.song;
    return (
      <div>
        <p>{ this.props.title }</p>
        <ul>
          {song.map((item) =>
            <Item number={this.number++} value={item} key={this.nuber} />
          )}
        </ul>
      </div>
    );
  }
}

  class Item extends Component {
    liStyle = {
      listStyleType: "none",
      textAlign: "left"
    };

    render () {
      return (
      <li style={this.liStyle}>{this.props.number}. {this.props.value}</li>
      );
    }
  }

export default App;

最後に

ステート、プロパティ、コンポーネントと制御構造を組み合わせるとより多彩な表現ができそうです。コンポーネントも繰り返し作っていくことでだんだん見慣れてきました♪

さて、ステートの機能をさらに使いこなすためには「Redux」を利用することになりそうです。Vue.jsでやった「Vuex」と同じ位置づけのツールです。次回以降ではそろそろReduxにも取り組んでいく予定です。それではまた!


※参考:Reactを習得するためにやったことまとめ
qiita.com