今日は、【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 = 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 = 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の処理さえかけば完成です。
# 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 = 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を書きましょう。
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
これで完成です!お疲れ様でしたー!
綺麗に動いていると思います。ダメだったらコメントください笑
それでは、大学の授業受けてきます笑