LoginSignup
31
27

More than 5 years have passed since last update.

【rails/非同期】js初心者がいいね機能をReact.jsで実装してみた。その①

Last updated at Posted at 2016-05-05

【2016/12/17 追記】
React(flux)を使ったブログエンジンを開発しました!
何か参考になれば嬉しいです!

Notee
https://github.com/funaota/notee


最近なにかと流行のreact先生に今回思い切ってチャレンジしてみる事にしました。(遅め笑)

react触った印象

  • VirtualDOMにはめっちゃ感動しました。
  • id指定して、innerTextをどうたらこうたらってやらなくていいこと
  • State変更するだけでViewも変更されるんは熱い!
  • 思ってたよりも簡単!

ちょっとなと思ったところ

  • jsxの書き方嫌いな人は嫌いそう笑
  • jsx内で条件分岐のcodeとか書きにくい(component化したほうがいいとかなんとか、まだよくわからん)
  • jsx内でインスタンス変数とかアクセス出来ない(?)

今回やったこと

今回やったことは、タイトル通り、『いいね機能の実装』です。
Facebookのいいね機能をイメージしてもらえれば大丈夫だと思います。

具体的なLikeモデルのSchemaは以下になっています。

Like
# == Schema Information
#
# Table name: likes
#
#  id         :integer          not null, primary key
#  user_id    :integer          not null
#  post_id    :integer          not null
#  created_at :datetime         not null
#  updated_at :datetime         not null
#

具体的なイベントの流れは

  • ①いいねボタンを押す
  • ②LikeモデルにajaxでPOSTする
  • ③いいねボタンのViewを更新する
  • ④いいね回数のViewを更新する

上記の流れでDELETE versionも実装しました。

さて早速実装内容について説明します。

①reactを使える環境にする

詳しくはここを見てください
https://github.com/reactjs/react-rails#reactjs-builds

Gemfile
gem 'react-rails', '~> 1.7.0'

$ bundle install
$ rails g react:install

config/environments/development.rb
Rails.application.configure do

  ...

  config.react.variant = :development

  ...

end

②Componentをgenerateします

rails g react:component Like

このコマンドをうつと、app/assets/javascripts/componentslike.js.jsxが生成されます。
このファイルに実際のコードを書いて行きます。

③とりあえず、Hello World!を表示させるためのjsを完成させ、react_componentで表示させる

Hello World!を表示させるためのjsはこんな感じ

like.js.jsx

Like = React.createClass({
  render: function() {
    return(
      <div>Hello World!</div>
    );
  }
});

View側はこう書く

posts.html.slim
- @posts.each do |post|
  p = post.title
  = react_component 'Like'

これで、HelloWorldが、各Postに表示されるはずです。
ここのHelloWorldをいいねボタンに変えて、処理をすれば完成です!
じゃあ、いよいよ本題に入ります。

④いいねButtonのView作成と、対応するメソッドを用意します。

Viewの作成

<button onClick={this.ajaxMain}>いいね!</button>
Buttonタグで作成し、onClickでjs内のメソッドを指定する

対応するメソッドの作成

ajaxMain: function(){
  console.log("hello world!");
}

とりあえず、hello worldとコンソールに表示させるコードにします。
以下が全体のコードになります。

like.js.jsx

Like = React.createClass({

  ajaxMain: function(){
    console.log("hello world!");
  }

  render: function(){
    return(
      <button onClick={this.ajaxMain}>いいね!</button>
    );
  }
});

これで、いいねボタンのViewが表示され、ボタンを押すと、
consoleに"hello world"に表示されるはずです。

⑤使用するStateを定義する

今回は以下のStateを持つ事にします。

  • いいねの合計数
  • いいねされているかどうかの状態
like.js.jsx

Like = React.createClass({

  getInitialState: function(){
      return {
          counts: 0,         //いいねの合計数
          is_liked: false    //いいねされているかどうかの状態
      };
  },

  ajaxMain: function(){
      console.log("hello world!");
  }

  render: function(){
      return(
        <button onClick={this.ajaxMain}>いいね!</button>
      );
  }
});

⑤LikeをCreateするメソッドを用意します。

Controllerの流れ

  • ①ajaxでparams[:post_id]を受け取る
  • ②Likeを作成する
  • ③jsonで、status(ajaxが成功したかどうか)、like(あとで使う笑)、counts(いいねの合計数)、liked(いいねされてるかどうか)を返す
likes_controller.rb
  def create
    @like = Like.new(user_id: current_user.id, post_id: params[:post_id])

    respond_to do |format|
      if @like.save
        format.html { redirect_to :back, notice: 'Like was successfully created.' }
        format.json { render json: {status: 'success', like: @like, counts: Like.where(post_id: @like.post_id).count, liked: true} }
      else
        format.html { render :new }
        format.json { render json: @like.errors, status: :unprocessable_entity }
      end
    end
  end

⑥ajaxでparams[:post_id]を送り、resuponseを受け取るコードを記述する

like.js.jsx

Like = React.createClass({
    ajaxMain: function(method){
        $.ajax({
            url: this.props.url,                               //このURLは次でセットします
            type:method,                                       //今回はPOSTで送ります
            dataType: 'json',
            cache: false,
            data: {post_id: this.props.post},                  //このpostも次でセットします
            success: function(data) {
                if(data.like){                                 //ここはあとで活きてきます笑
                    this.setState({is_liked: data.liked});     //responseのlikedをstateのis_likedに反映させます
                };
                this.setState({counts: data.counts});          //responseのcountsをstateのcountsにに反映させます
            }.bind(this),                                      //bindしないとthisが使えなくてエラりますw
            error: function(xhr, status, err) {
                console.error(this.props.url, status, err.toString());
            }.bind(this)
        });
    },

    render: function(){
        return(
            <button onClick={this.ajaxMain.bind(this, "POST")}>いいね!</button>
        );
    }
});

⑦view側で、propsにパラメーターを渡します。

api_likes_urlは、routeで指定したajaxのapiを指定します。環境に会わせて随時変更してください。

posts.html.slim
- @posts.each do |post|
  p = post.title
  = react_component 'Like', post: post.id, url: api_likes_url

これで、ひとまずLikeを非同期で作成するまで完成しました!

具体的なイベントの流れ

  • ①いいねボタンを押す
  • ②LikeモデルにajaxでPOSTする
  • ③いいねボタンのViewを更新する
  • ④いいね回数のViewを更新する

次は③から活きたいと思います。

今日もまた蛍の光がお店でなりだしたので、続きはまた明日!!
Reactの説明難しい…

その②もかきますた!

31
27
1

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
31
27