この記事はこんな方向けに書いています。
- RailsにReactを導入したい方
- jQueryのコーディングに限界を感じている方
- 話題のライブラリに触れたい方
- 非同期処理を実装したい方
今回はRailsとReactを使って『いいね機能』を実装する方法について解説していきます。Twitterなどで見かけるハートマークのやつですね。

Contents
Reactを触ったことがない方がいきなりコードを書くのは無理だと思うので、まず基本の学習をするのをおすすめします。
そこでおすすめなのがUdemyの下記講座です。Javascriptの基礎から始まり、タスク管理アプリ作成を通してReactの基礎を学ぶことができます。


またこの講座は2020年10月にリリースされた新しいものなので、最新のReactの技術を学ぶことができます。
なお今回もReactの環境構築が済んでいる前提で行いますので、まだの方はこちらの記事を先に読んでみてくださいね!(Webpackerなどバンドラーが必要になるので!)
今回解説で使用するアプリには『Board』『User』『Favorite』が存在することを前提にしています。
*Boardの部分は皆さんが作成したテーブル名でOKです。
ステップ1ー1 リレーションの準備編
class Board < ApplicationRecord
belongs_to :user
has_many :favorites, dependent: :destroy
def favorite_by(user)
favorites.find_by(user_id: user.id)
end
end
class User < ApplicationRecord
has_many :boards, dependent: :destroy
has_many :favorites, dependent: :destroy
end
class Favorite < ApplicationRecord
belongs_to :user
belongs_to :board
end
ステップ1ー2 ルーティングの設定編
今回作成したアプリのルーティングは下記コードのようになっています。なおユーザーのログイン機能を『devise』で実装しています。
Rails.application.routes.draw do
devise_for :users,
root to: 'boards#index
resources :favorites,only:[:create,:destroy]
resources :boards
end
ステップ1−3 コントローラーの設定編
class BoardsController < ApplicationController
before_action :authenticate_user!
def index
@boards = Board.all
end
favorites_controller.rbではcreateとdestroyの2つのアクションを用意します。
どちらも『render json: favorite』とjsonで返していることがポイントです。
通常だとアクションの結果をView(HTML)で表示しますが、今回はいいねを非同期処理にしたいのでViewに返しません。
class FavoritesController < ApplicationController
def create
favorite = current_user.favorites.create!(favorite_params)
render json: favorite
end
def destroy
favorite = Favorite.find(params[:id])
favorite.destroy!
render json: favorite
end
private
def favorite_params
params.require(:favorite).permit(:board_id)
end
end
Reactの環境構築ができたら、必要なファイルを作成していきます。
まずはjavascript配下にあるbundlesフォルダに『Favorite.jsx』を作成します。
作成できたら次のコードを貼り付けます。これがReactで重要な『コンポーネント』という部品です。
import PropTypes from 'prop-types';
import React, { useState } from 'react';
import { HeartFill } from 'react-bootstrap-icons';
import axios from 'axios'
axios.defaults.headers['X-CSRF-TOKEN'] = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
const Favorite = (props) => {
const { boardId, favoriteId } = props;
const [id, setId] = useState(favoriteId);
const [count, setCount] = useState(0)
const clicked = async () => {
if (id == null) {
const { data: { id = null } } = await axios.post('/favorites', { board_id: boardId })
id && setId(id);
} else {
await axios.delete(`/favorites/${id}`)
setId(null);
}
}
return (
<>
<HeartFill
color={id ? 'red' : '#616161'}
size={25}
onClick={clicked}
/>
</>
);
};
Favorite.propTypes = {};
export default props => <Favorite {...props} />;
なおコード内にある『board』は皆さんが作成したテーブルの名称によって変わります。
例えばArticleテーブルを作成した場合は、board_idのところがarticle_idなどになります。
コンポーネントができたら、bundle.jsを作成していきます。
javascript配下にあるpacksフォルダに『bundle.js』を作成し、下記コードを貼り付けます。
import ReactOnRails from 'react-on-rails';
import Favorite from '../bundles/Favorite';
// This is how react_on_rails can see the HelloWorld in the browser.
ReactOnRails.register({
Favorite,
});
ここでreact_on_railsやFavorite.jsxの読み込みをします。ここの記述を抜かすと正しく表示されないので注意です!!
最後にFavorite.jsxコンポーネントをView側で読み込みます。
@boards.each do |board|
.card_name
=board.name
.card_description
=board.description
.card_favorite
#Reactコンポーネントの読み込み
= react_component("Favorite",
props: { boardId: board.id, favoriteId:
board.favorite_by(current_user)&.id }, prerender: false)
コメントを残す