hina2go

主に技術系のこことか。最近React始めました。

React Routerのチュートリアル Lesson3

前回の続き。

hinathy.hatenablog.com

Lesson3 - Navigating With Link

今回は、ハイパーリンクをつけて/repos/aboutに画面遷移できるようにします。

ハイパーリンクをつける

ハイパーリングは、React Routerが提供するLinkコンポーネントを使います。 app/components/app.jsxを、以下のように修正します。

import React from 'react';
import { Link } from 'react-router';

class App extends React.Component {

  constructor(props) {
    super(props);
  }

  render() {
    return (
      <div>
        <h1>React Router Tutorial</h1>
        <ul role="nav">
          <li><Link to="/about">About</Link></li>
          <li><Link to="/repos">Repos</Link></li>
        </ul>
      </div>
    );
  }
  
}

export default App;

これで、/about/reposに遷移できるはずです。

まとめ

ソースコード

github.com

React Routerのチュートリアル Lesson2

前回の続き。

hinathy.hatenablog.com

Lesson2 - Rendering a Route

今回は、React Routerを導入して、About画面とRepos画面を追加します。

React Routerのインストール

事前に、React Routerをインストールしておきます。

$ npm install react-router --save

Appコンポーネント/に紐付ける

import React from 'react';
import ReactDOM from 'react-dom';
import { Router, Route, hashHistory } from 'react-router';

require('../node_modules/bootstrap/dist/css/bootstrap.css')

import App from './components/app'

ReactDOM.render((
    <Router history={hashHistory}>
      <Route path="/" component={App} />
    </Router>
  ),
  document.body.appendChild(document.createElement('div'))
);

画面を追加する

新たに、ReposAboutコンポーネントを追加します。

  • About
import React from 'react';
import ReactDOM from 'react-dom';

export default class About extends React.Component {

  constructor(props) {
    super(props);
  }
  
  render() {
    return (<div>About</div>);
  }

}
  • Repos
import React from 'react';
import ReactDOM from 'react-dom';

export default class Repos extends React.Component {

  constructor(props) {
    super(props);
  }

  render() {
    return (<div>Repos</div>);
  }

}

最後に、RouteでURLとコンポーネントを紐付けます。

import React from 'react';
import ReactDOM from 'react-dom';
import { Router, Route, hashHistory } from 'react-router';

require('../node_modules/bootstrap/dist/css/bootstrap.css');

import App from './components/app';
import About from './components/about';
import Repos from './components/repos';

ReactDOM.render((
    <Router history={hashHistory}>
      <Route path="/" component={App} />
      <Route path="/repos" component={Repos} />
      <Route path="/about" component={About} />
    </Router>
  ),
  document.body.appendChild(document.createElement('div'))
);

以上で、http://localhost:8080/#/aboutとかhttp://localhost:8080/#/reposにアクセスすると各ページが表示されるはずです。

まとめ

  • Routerをルートノードに配置する。
  • Routerノードの子要素にRouteノードを含める。
  • Routeノードで、URLとコンポーネントを紐付ける。

ソースコード

github.com

React Routerのチュートリアル Lesson1

React Routerにはチュートリアルreact-router-tutorialが用意されています。 Step by Stepで勉強して、React Routerに入門してみます。

Lesson 1 - Setting Up

この章は、チュートリアルのプロジェクトをセットアップするのみ。 react-webpack-seedをもとにセットアップしました。

簡単ですが、今回はここまで。

ソースコード

github.com

ReactでGithubのリポジトリブラウザを作ってみる (5)

前回の続き。

hinathy.hatenablog.com

お題

今回のお題は、表示するリポジトリがない場合は、Alertでメッセージを表示するようにしてみます。

まずは完成イメージ。

f:id:hinathy:20160429002041p:plain

どう実装するか?

リポジトリ数が0か否かを知っているのはRepositoryListなので、ここで実装するのが適切でしょう。

まずは、既存の処理をメソッドに追い出します。

  repositoryNodes(repos) {
    const repositoryNodes = repos.map((repo) => {
      return (<Repository key={repo.id} name={repo.name} description={repo.description} />);
    });

    return (
      <Table responsive striped condensed hover>
        <thead>
          <tr>
            <th>Name</th>
            <th>Description</th>
          </tr>
        </thead>
        <tbody>
          {repositoryNodes}
        </tbody>
      </Table>
    );
  }

次に、リポジトリが存在しない場合のAlert表示を追加します。

  noRepositoryAlert() {
    return (
      <Alert bsStyle="info">
        <Glyphicon glyph="info-sign" />{' '}
        No repositories are exist.
      </Alert>
    )
  }

render()内で、this.props.repositoriesのlengthに応じてレンダリングするノードを切り替えます。

  render() {
    const repos = this.props.repositories;
    return repos.length > 0 ? this.repositoryNodes(repos) : this.noRepositoryAlert();
  }

ソースコード

github.com

Githubではcさんとwさんは予約されているらしい

前回で一区切りついたGithub Repository Browser。

hinathy.hatenablog.com

いろんなユーザー名を入力して遊んでいたら、ふと一文字ユーザーのリポジトリが気になったので、aさんからwさんまで試してみました。

するとaさんとwさんに空きが。

早速、憧れの一文字ユーザーを取得するべくサインアップしようとすると、なんとUsername is a reserved wordですと。。

f:id:hinathy:20160428192010p:plain

なんのために予約してるんだろう。。

ReactでGithubのリポジトリブラウザを作ってみる (4)

前回の続き。

hinathy.hatenablog.com

お題

今回のお題は、react-bootstrapを導入して見た目をそれなりにしてみます。

ビフォー・アフター

react-bootstrapの導入前後でどう変わったか。先に結論を。

導入前

f:id:hinathy:20160428184812p:plain

導入後

f:id:hinathy:20160428184824p:plain

だいぶ良くなりましたね。

react-bootstrapの導入手順

以下のコマンドで、react-bootstrapをインストールします。

$ npm install react-bootstrap --save

CSSは別途読み込んであげる必要がありますので、app/views/layouts/application.html.erbにstylesheet_link_tagを追加します。

<!DOCTYPE html>
<html>
  <head>
    <title>Github Repository Browser</title>
    <%= csrf_meta_tags %>
    <%= action_cable_meta_tag %>

    <!-- (*)↓を追加 -->
    <%= stylesheet_link_tag    'https://maxcdn.bootstrapcdn.com/bootstrap/latest/css/bootstrap.min.css' %>
    <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track' => 'reload' %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track' => 'reload' %>
  </head>

  <body>
    <%= yield %>
  </body>
</html>

あとは、リファレンスを見ながらひたすら書き換えていく作業。

ソースコード

github.com

ReactでGithubのリポジトリブラウザを作ってみる (3)

前回の続き。

hinathy.hatenablog.com

お題

今回のお題は、Clearボタンの実装。

Clearボタンを押すと、ユーザー名のテキストボックスと、検索済みのリポジトリ一覧をクリアします。

f:id:hinathy:20160428170049p:plain

テキストボックスをクリアする

まずは、ユーザー名のテキストボックスのvalueを、ステートで管理します。value={this.state.username}を追加しました。

class SearchBox extends React.Component {
  ... (snip) ...
  render() {
    return (
          ... (snip) ...
          <input type="text" value={this.state.username} onChange={this.handleChange} placeholder="Enter username" />
          ... (snip) ...
    );
  }

次に、SearchBoxにClearボタンとClearボタンクリック時のイベントハンドラhandleClear()を追加します。 handleClear()では、setState()を介してテキストボックスの値をクリアするようにしています。

class SearchBox extends React.Component {
  ... (snip) ...
  handleClear(e) {
    this.setState({username: ''});
  }

  render() {
    return (
          ... (snip) ...
          <input type="button" value="Clear" onClick={this.handleClear} />
          ... (snip) ...
    );
  }
  ... (snip) ...
}

これでユーザー名をクリアすることができます。

constructorで、handleClear()をthisにbindするのをお忘れなく。

  constructor(props) {
    ... (snip) ...
    this.handleClear = this.handleClear.bind(this);
  }

リポジトリ一覧をクリアする

ClearボタンクリックのイベントをAppに通知するため、onClear()をPropに追加します。 SearchBoxは、Clearボタンクリック時にこの関数を呼び出します。

class SearchBox extends React.Component {
  ... (snip) ...
  handleClear(e) {
    this.props.onClear();
    this.setState({username: ''});
  }
  ... (snip) ...
}

SearchBox.PropTypes = {
  ... (snip) ...
  onClear: React.PropTypes.func.isRequired
};

Appでは、SearchBoxに追加されたonClearPropにコールバック関数handleClear()を渡し、handleClear()が呼び出された契機でthis.state.repositoriesをクリアします。

class App extends React.Component {
  ... (snip) ...
  handleClear() {
    this.setState({repositories: []});
  }

  render() {
    return (
      <div>
        <SearchBox onSubmit={this.handleSubmit} onClear={this.handleClear} />
        <RepositoryList repositories={this.state.repositories} />
      </div>
    );
  }
  ... (snip) ...
}

以上で実装完了です。

gyazo.com

ソースコード

github.com