LoginSignup
7
9

More than 5 years have passed since last update.

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

Last updated at Posted at 2016-05-06

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

具体的なイベントの流れ

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

③のいいねボタンのViewを更新するから説明して行きたいと思います。

前回の内容はこちら

【rails/非同期】js初心者がいいね機能をReact.jsで実装してみた。その①
http://qiita.com/funao/items/60aa3d7e36cf93e0d832

前回は⑥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)
        });
    },
    onClick: function(){
       this.ajaxMain("POST")
    },
    render: function(){
        return(
            <button onClick={this.onClick}>いいね!</button>
        );
    }
});

⑦次は、View側にいいね回数といいねボタンの状態を反映させます

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)
        });
    },
    onClick: function(){
       this.ajaxMain("POST")
    },
    render: function(){
        if(this.state.is_liked){
          return (
                <div>
                    <p>{this.state.counts}いいね</p>
                    <button onClick={this.onClick("DELETE")}>いいね 取り消し!</button>
                </div>
            );
        }else{
          return(
              <div>
                <p>{this.state.counts}いいね</p>
                <button onClick={this.onClick}>いいね!</button>
              </div>
          );
        }

    }
});

やったことは、まずいいねされているかどうかで条件分岐を行い、そののち、pタグ内にthis.state.countsに取得したいいね回数をぶち込んだだけです。

これで、stateを変更するだけで望んだViewが作成されるはずです。

⑧次にDELETE側の処理も書きましょう

さきほどの記述でonClick("DELETE")と書いたのでajaxでDELETEは送られるはずです。
なので、ControllerにDELETEの処理さえかけば完成です。

likes_controller.rb

# DELETE /likes/1
  # DELETE /likes/1.json
  def destroy
    @like = Like.find_by(user_id: current_user.id, post_id: params[:post_id])
    @like.destroy
    respond_to do |format|
      format.html { redirect_to :back, notice: 'Like was successfully destroyed.' }
      format.json { render json: {status: 'success', like: @like, counts: Like.where(post_id: params[:post_id]).count}, liked: false }
    end
  end

最後のlikedでしっかりとfalseを返してあげる事が大事です。

ここまででほぼほぼ完成しました。

あとは、初期設定のみです。
新規にこのページを見たときに、自分がすでにいいねしているのかどうなのか取得する必要があります。

こんな時に使うのがcomponentDidMountという関数です。
この関数は、Componentが読み込まれた後に呼ばれる関数で、iosでいうとviewDidLoadと同じものと思われます。ほぼ。

なので、ここで現在のいいねの状況といいね数を取得してViewに反映させれば今回のいいね機能実装は完成です。

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)
        });
    },
    componentDidMount: function(){
        this.ajaxMain('GET');
    },
    render: function(){
        if(this.state.is_liked){
          return (
                <div>
                    <p>{this.state.counts}いいね</p>
                    <button onClick={this.ajaxMain.bind(this, this.state.is_liked ? 'DELETE' : 'POST')}>いいね 取り消し!</button>
                </div>
            );
        }else{
          return(
              <div>
                <p>{this.state.counts}いいね</p>
                <button onClick={this.ajaxMain.bind(this, this.state.is_liked ? 'DELETE' : 'POST')}>いいね!</button>
              </div>
          );
        }

    }
});

ajaxでGETが渡されるので対応するControllerを書きましょう。

likes_controller.rb

  def already_exists
    like = Like.find_by(user_id: current_user.id, post_id: params[:post_id]) 
    render json: { status: 'success', like: like, counts: Like.where(post_id: params[:post_id]).count, liked: like.present?}
  end

これで完成です!お疲れ様でしたー!
綺麗に動いていると思います。ダメだったらコメントください笑

それでは、大学の授業受けてきます笑

7
9
3

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
7
9