Simple Instagram app with Rails 6 API and React. Part 3

rails g model Comment name:string comment:string
app > models > comment.rb
class Comment < ApplicationRecord
validates_presence_of :name, :comment
belongs_to :picture
end
class Picture < ApplicationRecord
validates_presence_of :img_link, :created_by
has_many :comments
end
rails g controller comments index show create update destroy
Rails.application.routes.draw do
resources :pictures, only: [:show, :destroy, :index, :create, :update] do
resources :comments, only: [:index, :show, :create, :update, :destroy]
end
end
rails g migration add_pictures_to_comments picture:references
rails db:migrate
Reference to picture on comments table
class CommentsController < ApplicationController
before_action :set_picture #find a picture before running any of the actions here
before_action :set_picture_comment, only: [:show, :destroy]
# GET pictures/pid/comments
def index
render json: @picture.comments, status: :ok
end
# GET pictures/pid/comments/id
def show
render json: @picture
end
# POST pictures/pid/comments
def create
@picture.comments.create!(comment_params)
render json: @picture.comments, status: :created
# when we submit a form we want to send back the comments of a # picture as the response.this way we can update the DOM
enddef update
@comment.update(comment_params)
head :no_content
end
# DELETE pictures/pid/comments/id
def destroy
@comment.destroy
@picture.comments
end
private
def comment_params
params.permit(:name, :comment)
end
def set_picture
@picture = Picture.find(params[:picture_id])
end
def set_picture_comment
@comment = @picture.comments.find_by!(id:params[:id]) if @picture
end
end
Our comment creation should return the picture, we can then make a GET request to the same route to get the comment.

Now to React

npm i uuid --save
# first we import necessary modules/filesimport React, { Component } from "react";
import API_URL from "./helpers/apiHelper";
import axios from "axios";
import "../styles/Comment.css";
import uuid from "uuid";
# create a class component
export default class Comments extends Component {
constructor(props) {
super(props);
this.state = {
comments: [],
name: "",
comment: ""
};
this.handleSubmit = this.handleSubmit.bind(this);
this.handleChange = this.handleChange.bind(this);
}
# When the comment component mounts, we should load the comments
componentDidMount() {
# here we desturcutre our props. it's neater to write it like this.
const { pid } = this.props;
# we pass in the pid as a prop. we get the pid from the pictures #component
axios.get(`${API_URL}/pictures/${pid}/comments`).then(response => {
# when we get the result of our call to the server. we load all the # comments into an array
this.setState({
comments: response.data
});
});
}
# this handles when a new comment is created
handleSubmit(e) {
e.preventDefault(); # prevents the page from reloading
const { name, comment } = this.state;
const { pid } = this.props;
const body = {
name,
comment
};
# send the comment to the server
axios.post(`${API_URL}/pictures/${pid}/comments`, body).then(response => {
# get the response which are comments belonging to a pic
this.setState({ comments: response.data });
});
this.setState({ name: "", comment: "" });
} # once the user hits submit, clear the form fields
handleChange(e) {
this.setState({ [e.target.name]: e.target.value });
}
render() {
const { comments } = this.state;
const displayAllComments = comments.map(comment => (
<div className="commentWrapper" key={uuid()}>
<p className="ShowComment">
<strong className="commentName">{comment.name}</strong>
<span className="comment">{comment.comment}</span>
</p>
</div>
));
return (
<div>
<div className="view">View all comments</div>
{displayAllComments}
<form onSubmit={this.handleSubmit} className="commentForm">
<input
name="name"
id="name"
type="text"
value={this.state.name}
onChange={this.handleChange}
placeholder="Your name: "
className="commentInput"
></input>
<input
name="comment"
id="comment"
type="text"
value={this.state.comment}
onChange={this.handleChange}
placeholder="Your comment: "
className="commentInput"
></input>
<div>
{" "}
<small>hit enter to add comment</small>
</div>
<button type="submit" className="submitComment"></button>
</form>
</div>
);
}
}
const displayAllPictures = pictures.map(picture => (
<div key={uuid()}>
<PictureCard
key={picture.id}
uName={picture.created_by.toLowerCase()}
displayPicture={picture.img_link}
picture={picture.img_link}
caption={picture.caption}
increaseLikes={this.increaseLikes}
pid={picture.id}
/>
<Comments pid={picture.id} />
<Likes dateCreated={picture.created_at} likes={picture.likes} />
</div>
));
.ShowComment {
margin-left: 1.1em;
margin-top: 0.2em;
}
.comment {
margin-left: 0.5em;
}
.view {
margin-top: -0.8em;
margin-left: 1em;
color: grey;
}
.commentName {
margin-top: -2.5em;
}
.commentForm {
margin-left: 1em;
}
.commentInput {
border: none;
border-bottom: 1px solid black;
margin-bottom: 0.5em;
}
.submitComment {
visibility: hidden;
}
<FontAwesomeIcon icon={faTrashAlt} onClick={this.handleDelete} />
handleDelete(e) {
const { pid } = this.props;
const cid = e.currentTarget.getAttribute("cid");
axios.delete(`${API_URL}/pictures/${pid}/comments/${cid}`).then(
this.setState({
comments: response.data,
notification: "Comment deleted"
})
);
setTimeout(() => {
this.setState({
notification: ""
});
}, 3000);
}

--

--

--

Growth at Moni(YC W22) | Adebola.dev

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Unity VCS with Git and GitHub

Validate Email Workflows with a Serverless Inbox API

Looker Migration in Trendyol

Why a Spring Cloud Config Server is Crucial to a Good CI/CD Pipeline and How To Set It Up (Pt 1)

Deriving Data Structures

Get into Redis & Redis Boot Camp

Deploying TabPy in Enterprise: Scaling and Hardening in Kubernetes

Major Updates & Metatime Officially Launch

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Adebola Adeniran

Adebola Adeniran

Growth at Moni(YC W22) | Adebola.dev

More from Medium

Introduction to Kao js

Introduction to NodeJS

Node.js

Basics and Getting Started with Node.js