LoginSignup
82
85

More than 5 years have passed since last update.

話題かもしれないReactを使って簡単なアプリケーションを作ってみた。

Last updated at Posted at 2014-10-15

数年前からjavascriptのフレームワークが数多く出てきたけど、その中でも最近話題かもしれないreactについて勉強してみた。
Facebook製で、Facebook、Instagram、GitHub (Atom) という大御所たちに使われたりしている。

作ったアプリケーション

Qiitaのタグを取得してタグごとに記事一覧を表示するもの。
トップは新着記事一覧を表示。

スクリーンショット 2014-10-15 22.13.47.png

デモ

トレンド

Googleのトレンドで見てみるとじわじわと人気が出てきているのがわかる。
backboneはいわずもがな、angularも直近だけ見ると落ち込んでいるように見えるが、reactはじわじわと伸びている。
https://www.google.co.jp/trends/explore#q=react.js%2C%20backbone.js%2C%20angular.js%2C%20vue.js&cmpt=q

スクリーンショット 2014-10-15 22.02.16.png

Github

大雑把な説明

使ったもの

jsのフレームワークはMVCじゃなくてMVWとか色々あるけどreactはVだけに特化したもの。
なので他のフレームワークと容易に共存できる。

ただ、今から紹介するテストではそんなめんどくさいことはせずにjQueryのajaxでAPIをとってきて、それをReactを使ってレンダリングしている感じ。
ルーティングはreact-routerというライブラリを使用した。
なので一応reactのみで動いていると言ってもいいでしょう。

使ってみた所感として、angularとは違って最初はとっかかりにくいけど、慣れると使いやすくなってくる。

あと別に使わなくてもいいみたいだけどJSXを使うのを推奨しているみたいなので使ってみた。これも慣れればすぐに使えるはず。

ドキュメントが英語しかないので、せっかくだし日本語にしてまとめていきたいなーと思ったけど、めんどくさくなったのでソースコードをそのまま貼り付ける。

ここなんやねんっていうのがあればコメントいただければ分かる範囲で答えます。

クロスオリジン

qiitaのAPIを叩くとき、たまにクロスオリジンで怒られるのはなんでだろうか。
怒られる時と怒られない時があるのは解せない。
あとiframeで記事詳細を埋め込もうとしたけど、これもクロスオリジンで怒られたので断念。
なくなく記事詳細は別タブで開くようにした。

ソースコード

html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Hello React</title>
    <!-- Not present in the tutorial. Just for basic styling. -->
    <link rel="stylesheet" href="css/index.css" />
  </head>
  <body>
    <div id="content"></div>
  </body>
</html>
<script src="scripts/libs/react-0.11.2.js"></script>
<script src="scripts/libs/JSXTransformer-0.11.2.js"></script>  
<script src="scripts/libs/react-router.js"></script>
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="scripts/app.js" type="text/jsx"></script>
javascript
/** @jsx React.DOM */

var Router = ReactRouter;
var Route = ReactRouter.Route;
var Routes = ReactRouter.Routes;
var DefaultRoute = ReactRouter.DefaultRoute;
var Link = Router.Link;

var HOST = 'https://qiita.com/api/v1';
var http = {
  items: function() {
    return $.ajax({
      url: HOST+'/items',
      dataType: 'json'
    });
  },
  itemsIntag: function(tag) {
    return $.ajax({
      url: HOST+'/tags/'+tag+'/items',
      dataType: 'json'
    });
  },
  tags: function() {
    return $.ajax({
      url: HOST+'/tags',
      dataType: 'json'
    });
  }
};

var Main = React.createClass({
  getInitialState: function() {
    return {data: []};
  },
  componentDidMount: function() {
    var that = this;
    if (this.props.params.tagId !== undefined) {
      http.itemsIntag(this.props.params.tagName).done(function(data) {
        that.setState({data: data});
      });
    } else {
      http.items().done(function(data) {
        that.setState({data: data});
      });
    }
  },
  componentWillReceiveProps: function(nextProps) {
    var that = this;
    if (nextProps.params.tagName !== undefined) {
      http.itemsIntag(nextProps.params.tagName).done(function(data) {
        that.setState({data: data});
      });
    } else {
      http.items().done(function(data) {
        that.setState({data: data});
      });
    }
  },
  render: function() {
    var work = this.state.data.map(function(work) {
      return (
        <List key={work['id']} title={work['title']}
               category={work['Category']}
                url={work['url']}
                image={work['user']['profile_image_url']}>
        </List>
      );
    });
    return (
      <section className="main">
        <ul>
          {work}
        </ul>
      </section>
    );
  }
});

var List = React.createClass({
  render: function() {
    return (
      <li className="list">
        <a href={this.props.url} target="_blank">
          <span ref="img" className="image">
            <img src={this.props.image} width="80"/>
          </span>
          <span className="name">
            <p className="title">{this.props.title}</p>
          </span>
        </a>
      </li>
    );
  }
});

var About = React.createClass({
  render: function() {
    return (
      <section className="about">
        <h1 className="bold">React</h1>
        <p>React is a JavaScript library for creating user interfaces by Facebook and Instagram.</p>
        <br/>
        <p>Many people choose to think of React as the V in MVC.</p>
        <br/>
        <p>Simply express how your app should look at any given point in time,</p>
        <p>and React will automatically manage all UI updates when your underlying data changes.</p>
        <br/>
        <p>When the data changes, React conceptually hits the refresh button, and knows to only update the changed parts.</p>
        <br/>
        <p><a href="http://facebook.github.io/react/">{'http://facebook.github.io/react/'}</a></p>
      </section>
    );
  }
});

var Menu = React.createClass({
  getInitialState: function() {
    return {data: []};
  },
  componentDidMount: function() {
    var that = this;
    http.tags().done(function(data) {
      that.setState({data: data});
    });
  },
  render: function() {
    var tags = this.state.data.map(function(tag) {
      return (
        <li key={tag['name']}><Link to="tag" params={{tagName: tag['name']}}>{tag['name']}</Link></li>
      );
    });
    return (
      <ul>
        <li><Link to="about">{'What\u0027s React?'}</Link></li>
        <span>TAGS</span>
        {tags}
      </ul>
    );
  }
});

var App = React.createClass({  
  render: function() { 
    return (
      <div className="container">
      <header>
        <h1><a href="#" className="title">REACTJS TEST</a></h1>
        <Menu />
      </header>
      <this.props.activeRouteHandler/>
      </div>
    );
  }
});

var routes = (
  <Routes>
    <Route name="app" path="/" handler={App}>
      <Route name="about" handler={About}/>
      <Route name="tag" path=":tagName" handler={Main} />
      <DefaultRoute handler={Main}/>
    </Route>
  </Routes>
);

React.renderComponent(routes, document.getElementById('content'));
82
85
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
82
85