【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は以下になっています。
# == 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
gem 'react-rails', '~> 1.7.0'
$ bundle install
$ rails g react:install
Rails.application.configure do
...
config.react.variant = :development
...
end
②Componentをgenerateします
rails g react:component Like
このコマンドをうつと、app/assets/javascripts/components
にlike.js.jsx
が生成されます。
このファイルに実際のコードを書いて行きます。
③とりあえず、Hello World!を表示させるためのjsを完成させ、react_componentで表示させる
Hello World!を表示させるためのjsはこんな感じ
Like = React.createClass({
render: function() {
return(
<div>Hello World!</div>
);
}
});
View側はこう書く
- @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 = React.createClass({
ajaxMain: function(){
console.log("hello world!");
}
render: function(){
return(
<button onClick={this.ajaxMain}>いいね!</button>
);
}
});
これで、いいねボタンのViewが表示され、ボタンを押すと、
consoleに"hello world"に表示されるはずです。
⑤使用するStateを定義する
今回は以下のStateを持つ事にします。
- いいねの合計数
- いいねされているかどうかの状態
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(いいねされてるかどうか)を返す
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 = 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.each do |post|
p = post.title
= react_component 'Like', post: post.id, url: api_likes_url
これで、ひとまずLikeを非同期で作成するまで完成しました!
具体的なイベントの流れ
①いいねボタンを押す②LikeモデルにajaxでPOSTする- ③いいねボタンのViewを更新する
- ④いいね回数のViewを更新する
次は③から活きたいと思います。
今日もまた蛍の光がお店でなりだしたので、続きはまた明日!!
Reactの説明難しい…
その②もかきますた!