Help us understand the problem. What is going on with this article?

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

More than 5 years have passed since last update.

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

作ったアプリケーション

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

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

デモ

http://ytakzk.github.io/react-sample/

トレンド

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

https://github.com/ytakzk/react-sample

大雑把な説明

使ったもの

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'));
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away