WEB開発の門外漢がReactでお試しSPAを作成する

作成前

今までPythonでデータ分析とかスクレイピングのためのプログラムは書いてきた。
でも、WEB開発はあまりやってこなかった。
自分で何かWEBサービスを作ってみたいという思いがむくむくと湧いてきた。
少しずつWEB開発をやっていこう。
とりあえずサーバーサイドは脇に置いて、フロントエンドから取り掛かろう。

道具の選択

Javascriptのフロントエンドライブラリは、無難にReactを選択する。
React Nativeもあるので、将来的にはスマホアプリへの広がりも少し期待した。

いきなりゴリゴリと本格的にサービスを開発するわけにもいかない。
まずは何か見本ページをパクっ...真似てReactに慣れよう。
ここにReactで作成したWEBアプリがたくさんあるので、その中からこれを真似る。
CSSフレームワークはBootstrapが使われているようだ。

何作る

まんま見本サイトをパクってロボットの写真を使うのは趣がない。
ジャズのプレイヤーの写真に差し替えてみよう。
ジャズマン名鑑のようなものを作ろう。

何やりたい

ページを変えた時に画面全体を再描画するのではなく、パネル内の文字と写真だけを描画する」という機能を実装してみたい。
実際に試作してみたSPAはこちら

手を付けなかったもの

ゆくゆくは使ってみないといけないだろうが、今回は小規模な開発なのでFluxやReduxは使わない。
また、サーバー部分はとりあえず脇に置いているので、AWSとかは使わない。
デプロイがとても簡単にできるGithub Pagesを使う。

詰まったところ

作業はReact公式やReact本、Web上の情報を収集すれば、大体進めていける。
とはいえ、「現在のページをどのように管理するか、またページが変わったことをどのようにパネル部分のコンポーネントに伝えるか」で詰まった。
どうやら、この部分はReactでアプリを構築していく上で基礎の部分であり、これをきちんと理解できていないとWebアプリっぽい機能は全く実装できないようだ。

ページ管理

そもそもどのようにページを管理したいいのかが分からない。
React-Bootstrapの公式を眺めた。
どうやら、今何ページ目が開かれているかはコンポーネントが持つ内部状態で管理するらしい。
ちなみにコンポーネント間のデータの受け渡しについては、こちらのページに詳しく書いてある。

以下の手順でデータの受け渡しをやる。

  1. ページネーションのボタンがクリックされる。
  2. ページが変更されたことを、ページネーションの子コンポーネントからをページを管理している親コンポーネントに通知する
  3. 通知を受け、親コンポーネントが内部状態として持っている「activePage」を書き換える
  4. コンポーネントからパネル部分の子コンポーネントへページが変更されたことを通知する
  5. 変更されたページに属するジャズマンの写真と名前を描画する

コンポーネントと子コンポーネント間の連携

Pageのコンポーネントと親コンポーネントの連携は以下のように行う。

  1. React-BootstrapのPaginationコンポーネントを子コンポーネントとして配置
  2. コンポーネントのメソッドとしてactivePageを書き換えるイベントハンドラを定義
  3. そのイベントハンドラthis.props経由でPaginationコンポーネントへと渡し、onSelect属性に代入

また、写真を描画するItemsコンポーネントの方と親コンポーネントの連携は以下のように行う。

  1. コンポーネントactivePageの値をthis.props経由でItemsコンポーネントに渡す。
  2. 親からactivePageの値を受け取り、その値によって描画する写真を変える。

親は以下のようなコードになる。

class Center extends Component {  
      
    constructor(props) {  
        super(props)  
        this.state = {  
            //ここで現在のページ数を管理する  
            activePage: 1  
        }  
    }  
      
    //ページ数を書き換えるメソッド  
    updateActivePage (e) {  
        this.setState({activePage: e})  
    }  
  
    render () {  
  
        const activePage = this.state.activePage  
        const updateActivePage = (e) => this.updateActivePage(e)  
  
        return  (  
            <Grid className="container-fluid">  
                <Title />  
                <Page activePage={activePage}  
                      //このようにしてPageコンポーネントにupdateActivePageを渡す  
                      updateActivePage={updateActivePage} />  
                //ItemコンポーネントにacitivePageの値を渡す  
                <Items page={activePage} />  
                <Page activePage={activePage}  
                      //このようにしてPageコンポーネントにupdateActivePageを渡す  
                      updateActivePage={updateActivePage} />  
            </Grid>  
        )  
    }  
}  

ちなみに、子のPageコンポーネントのこのようになっている。
Itemコンポーネントの方も値の受け取り方は同じである。

render(){  
    const pageNumber = Math.ceil(this.getPageNum() / 12)  
  
    //親から受け渡されたupdateActivePage()はこのように受け取る。  
    const updateActivePage = this.props.updateActivePage  
  
    return (  
        <Pagination  
            prev  
            next  
            first  
            last  
            ellipsis  
            boundaryLinks  
            items={pageNumber}  
            activePage={this.props.activePage}  
            //SelectイベントによってactivePageを書き換えるようupdateActivePage()をセットする。  
            onSelect={(e) => updateActivePage(e)}  
          />)  
}  

最後に

SPAを作成したと言っても、これはまだ試作段階なので、不十分な点が色々とある。
色々と作っていって、Reactに早く慣れていきたい。