Cloudinary React attachment upload is very slow - mysql

I have a file upload feature using Cloudinary in my React app. When I uploaded the file, it is saved to both Cloudinary and MySQL. I managed to upload things including PDF documents, however the upload is very slow. It takes more than 10 seconds to redirect to a new page after a successful upload. I am just wondering how I could improve it since it is affecting my system's performance.
Front-end
import React, {useState, useContext} from 'react'
import {Form, Button, Card} from 'react-bootstrap'
import Axios from 'axios';
import { useHistory } from 'react-router-dom';
function AddAttachment() {
const history = useHistory();
const [fileSelected, setFile] = useState();
const uploadImage = async(e) => {
e.preventDefault();
const formData = new FormData();
formData.append("file", fileSelected);
formData.append("upload_preset", "xxxxx");
const r = await Axios.post("https://api.cloudinary.com/v1_1/xxxxxx/image/upload", formData).then((response) => {
Axios.post("http://localhost:3001/uploadattachment",{
imageUrl: response.data.secure_url,
}).then(() => {
window.alert('You have successfully uploaded an image!');
history.push(`/viewproject`);
})
})
}
return (
<div className="d-flex justify-content-center">
<Card style={{ width: '70%' }}>
<Form onSubmit={uploadImage} className = "m-3 p-5">
<Form.Group className="mb-3" controlId="image">
<h3>
Add new attachment
</h3>
<hr/>
<Form.Control type="file"
onChange={(event) => {
setFile(event.target.files[0]);
}}
/>
</Form.Group>
<div className = "d-flex flex-end justify-content-end align-items-end mt-3">
<div>
<Button type = "submit" style={{color:'white', backgroundColor:'#104271'}}>Save</Button>
</div>
</div>
</Form>
</Card>
</div>
)
}
export default AddAttachment
Back-end (NodeJS)
app.post("/uploadattachment", (req,res) => {
const url = req.body.imageUrl;
try{
const addPicture = "INSERT INTO project_attachment(project_attachment_url) VALUES (?);"
db.query(addPicture, url, (err, result) => {
res.send(result);
})
}
catch(err){
console.log(err);
}
})
Just wondering if there are any part of my codes that could be improved? Thank you!

I don't know if this will improve your performance, but it will improve your code.
I strongly recommend you to do the upload in your backend using the npm package that cloudinary has, also it has transform and optimization assets.
With this you will call to your backend and it will be the responsible of handling the files repository and database. And your front-end will be cleaner
Hope it helps you.
app.post("/uploadattachment", (req,res) => {
try{
const upload_result = await cloudinary.v2.uploader.upload(req.file, {upload_preset: req.preset});
const addPicture = "INSERT INTO project_attachment(upload_result.secure_url) VALUES (?);"
db.query(addPicture, url, (err, result) => {
res.send(result);
})
}
catch(err){
console.log(err);
}
})

Related

Not able to delete my column from my Mysql table

I tried everything I think but no able to delete data from my mysql table using axios.delete with ProjectId (table ids).
Here's my code for where I declared my function, and as you can see I am passing the function through props
import React from "react";
import Projects from "../Projects/Projects";
import "./pluseProjects.css";
import {IoIosAddCircleOutline} from "react-icons/io"
import { Link } from "react-router-dom";
import {BiChevronLeftCircle,BiChevronRightCircle} from "react-icons/bi"
import {IoRefreshCircleOutline} from "react-icons/io5";
import axios from "axios";
export default function PluseProjects() {
const [addNewProjects, setAddNewProjects ] = React.useState(false)
const [getQuery,setGetQuery] = React.useState({
projectList:[]
})
function onStateChange() {
setAddNewProjects(!addNewProjects)
}
function getProjectList() {
axios.get(`http://localhost:3060/projects`)
.then((response) => response.data)
.then(response2 => {
setGetQuery({projectList : response2})
})
}
function onDeleteId(ProjectId) {
axios.delete(`http://localhost:3060/deleteprojects/${ProjectId}`)
getProjectList();
}
return(
<div className="Section-Projects" >
<div className="top-projects">
<h1>My Projects </h1>
<button onClick={getProjectList} className="Refresh"><IoRefreshCircleOutline /></button>
<Link to={addNewProjects?'/AddProjects':""} ><button className="Add-newProject" onClick={onStateChange}><IoIosAddCircleOutline /></button></Link>
</div>
<div className="Projects">
<button className="arrowLeft"><BiChevronLeftCircle /></button>
<div className="Single">
{getQuery.projectList.map((gettingQuery) =>
<Projects
onHandleDelete={onDeleteId(gettingQuery.ProjectId)}
ProjectName={gettingQuery.ProjectName}
Discription={gettingQuery.Discription}
git={gettingQuery.git}
Img={gettingQuery.Img}
/>
)}
</div>
<button className="arrowRight"><BiChevronRightCircle /></button>
</div>
</div>
)
};
Here is my server.js code - I am telling SQL to delete this column with some ProjectId:
const express = require('express');
const cors = require('cors')
const PORT = 3060;
const db = require('./Database')
const bodyParser = require('body-parser');
const { response } = require('express');
const app = express();
app.use(cors());
app.use(bodyParser.json());
app.get('/projects', (req,res) => {
const TASK_QUERY = `SELECT * FROM newproject`;
db.query(TASK_QUERY , (err, response) => {
if(err) res.status(404).send('something is wrong')
else res.send(response)
})
});
app.post('/addProjects', (req,res) => {
const ADD_QUERY = `INSERT INTO newproject (ProjectName,Discription,git,Img) VALUES('${req.body.ProjectName}','${req.body.Discription}','${req.body.git}','${req.body.Img}')`;
db.query(ADD_QUERY, (err) => {
if (err) console.log(err)
else res.send('Query added successfully')
})
} );
app.delete('/deleteprojects/:ProjectId', (req,res) => {
console.log(req.params.ProjectId)
const DELETE_TASK = `DELETE FROM newProjects WHERE ProjectId = ${req.params.ProjectId}`
db.query(DELETE_TASK, (err,res) => {
if (err) console.log(err)
})
})
app.listen(PORT, () => {
console.log('app is listening on port 3000')
})
And here's where I am calling my function - I think my props management is all right. Am I calling the function the wrong way?
import React from "react";
import "./Projects.css"
import {RxCrossCircled} from "react-icons/rx"
export default function Projects(props) {
return(
<div className="Project" >
<div className="Image">
<img src={props.Img} alt=""/>
<button className="cross" onClick={props.ProjectId}><RxCrossCircled /></button>
</div>
<div className="Bottom">
<h3>{props.ProjectName}</h3>
<p>{props.Discription}</p>
{props.git}
</div>
</div>
)
};
If you see a http call in the network tab when you trigger the function (clicking the delete button etc). That means your frontend(react part) is working fine. Also i clearly see that you are missing an res.send() statement in your delete route in your server.js.
app.delete('/deleteprojects/:ProjectId', (req, res) => {
console.log(req.params.ProjectId)
const DELETE_TASK = `DELETE FROM newProjects WHERE ProjectId = ${req.params.ProjectId}`
db.query(DELETE_TASK, (err, res) => {
if (err) console.log(err)
res.status(200).send({}) // you missed this
})
})
Your onHandleDelete is not being used in the Projects component. And the ProjectId is not passed as a prop. In the PluseProjects you immediately call the onDeleteId function you should call it via an anonymous function.
PluseProjects
{
getQuery.projectList.map((gettingQuery) => (
<Projects
onHandleDelete={() => onDeleteId(gettingQuery.ProjectId)} // () =>
ProjectName={gettingQuery.ProjectName}
Discription={gettingQuery.Discription}
git={gettingQuery.git}
Img={gettingQuery.Img}
/>
));
}
Projects
export default function Projects(props) {
return (
<div className="Project">
<div className="Image">
<img src={props.Img} alt="" />
<button className="cross" onClick={props.onHandleDelete}> // change ProjectId to onHandleDelete
<RxCrossCircled />
</button>
</div>
<div className="Bottom">
<h3>{props.ProjectName}</h3>
<p>{props.Discription}</p>
{props.git}
</div>
</div>
);
}

Not able post data from useState to Mysql

I am trying to post the input data from useState to Mysql but its just not happening. While I am able to get the data from the database to the page but when it comes to posting I don't know how to send data from state hooks to mysql when there are many values. Please take a look
Code from where i am sending the form data
import React,{useState , useRef} from "react";
import "./AddProjects.css"
import axios from "axios";
import Projects from "../Projects/Projects";
import {BiChevronLeftCircle,BiChevronRightCircle} from "react-icons/bi"
export default function AddProjects() {
const [AddProjects,setAddProjects] = useState({
ProjectName:"",
Discription:"",
git:"",
Img:""
})
const [getQuery,setGetQuery] = useState({
projectList:[]
})
const inputFile = useRef(null)
function handleChange(e) {
const {name , value} = e.target;
setAddProjects(newProjects => ({
...newProjects,[name]:value
}))
}
function imgChange(e) {
setAddProjects({ ...AddProjects, Img: URL.createObjectURL(e.target.files[0]) });
}
function getProjectList() {
axios.get(`http://localhost:3060/projects`)
.then((response) => response.data)
.then(response2 => {
setGetQuery({projectList : response2})
})
}
function onSubmitHandler(e) {
axios.post(`http://localhost:3060/addProjects`,{
ProjectName: AddProjects.ProjectName,
Discription:AddProjects.Discription,
git:AddProjects.git,
Img:AddProjects.Img
})
getProjectList()
}
return(
<>
<div className="AddProjects">
<form onSubmit={onSubmitHandler} method="POST" encType="multipart/form-data" >
<h2>Add New Project</h2>
<input type="text" placeholder="Project Name..." name="ProjectName" onChange={handleChange}/>
<input type="text" placeholder="Project Discription..." name="Discription" onChange={handleChange}/>
<input type="text" placeholder="Git Repository/Code..." name="git" onChange={handleChange}/>
<input type="file" accept="image/jpg,image/jpeg" name="Img" onChange={imgChange} ref={inputFile} />
<button type="button"onClick={() => inputFile.current.click()}>Add New Image</button>
<button type="submit" >Submit Project</button>
</form>
<button onClick={getProjectList}>click me </button>
</div>
<div>
<div className="Section-Projects" >
<h1>My Projects </h1>
{/* <Link to={checkBox?'/AddProjects':""} ><button className="Add-newProject" onClick={onStateChange}><IoIosAddCircleOutline/></button></Link> */}
<div className="Projects">
<button className="arrowLeft"><BiChevronLeftCircle /></button>
<div className="Single">
{getQuery.projectList.map((gettingQuery) =>
<Projects
ProjectId={gettingQuery.ProjectId}
ProjectName={gettingQuery.ProjectName}
Discription={gettingQuery.Discription}
git={gettingQuery.git}
Img={gettingQuery.Img}
/>
)}
</div>
<button className="arrowRight"><BiChevronRightCircle /></button>
</div>
</div>
</div>
</>
)
};
As you can see i want to send 4 things to the mysql table but i don't think the this is the way to do it and i just can't figure it out
Code for my file that is sending data
const express = require('express');
const cors = require('cors')
const PORT = 3060;
const db = require('./Database')
const bodyParser = require('body-parser');
const { response } = require('express');
const app = express();
app.use(cors());
app.use(bodyParser.json());
app.get('/projects', (req,res) => {
const TASK_QUERY = `SELECT * FROM addprojects.newproject`;
db.query(TASK_QUERY , (err, response) => {
if(err) res.status(404).send('somthings wrong')
else res.send(response)
})
});
app.post('/addProjects', (req,res) => {
const ADD_QUERY = `INSERT INTO addprojects.newproject VALUES('${req.body.data}')`;
db.query(ADD_QUERY, (err) => {
if (err) console.log(err)
else res.send('Query added sucsessfully')
})
} );
app.listen(PORT, () => {
console.log('app is listning to port 3000')
})
I think while the post method is correct the Value is not so please help I am on this for 2 days Any suggestion will be help full
INSERT INTO tablename (columnName1, columnName2) VALUES ('Company Inc', 'Highway 37')
For backend:
You don't mention the columns name, it doesn't know which field belongs to which column in the table.
For Frontend:
axios.post(`http://localhost:3060/addProjects`,{
ProjectName: AddProjects.ProjectName,
Discription:AddProjects.Discription,
git:AddProjects.git,
Img:AddProjects.Img
})
ProjectName,Discription,git,Img make these keys name exact to your column names.
And you are uploading an image in this api so convert your data from front in formdata then pass that data in api and on backend you will that data in formdata

Confused about changing state in a certain way

I have a page in NextJS for editing an sql row and sending it back. I have fetched all the rows from the table and then have set the state to be the single row which matches the query parameter in the useRouter hook. Now, after I have edited the data in the row, what is a good way to POST it back to the backend?
Below is my React code:
import { React, useEffect, useState } from "react";
import { useRouter } from "next/dist/client/router";
const axios = require("axios");
export default function Edit() {
const [data, setData] = useState([]);
const router = useRouter();
const onSubmitHandler = (e) => {
e.preventDefault();
axios.post("/api/cards", data);
};
useEffect(() => {
const fetchData = async () => {
await axios
.get("/api/cards")
.then((res) => {
if (res.data) {
res.data.map((element) => {
if (element.ID == router.query.card) {
setData(element);
return;
}
return;
});
}
})
.catch((err) => {
console.log(err);
});
};
if (router.isReady) {
fetchData();
}
}, [router.isReady, router.query.card]);
return (
<form onSubmit={onSubmitHandler}>
<label htmlFor="front">Front</label>
<input
defaultValue={data.Front}
id="front"
onChange={(e) => setData({ ...data, Front: e.target.value })}
></input>
<label htmlFor="back">Back</label>
<input
defaultValue={data.Back}
id="back"
onChange={(e) => setData({ ...data, Back: e.target.value })}
></input>
<button type="submit">Add Word</button>
</form>
);
}
Below is my backend code
if (req.method === "POST") {
const { front, back, type } = req.body.data;
const id = uuidv4();
db.query(
`INSERT INTO deck VALUES('${front}', '${back}', '${type}', '${id}')`,
(err, rows, fields) => {
if (!err) {
res.json(rows);
} else {
console.log(err);
}
}
);
}
Its good to post the edited data after submiting the form..
const onSubmitHandler = async (e) => {
e.preventDefault();
try {
await axios.post("/api/cards", data);
// react-toast or something like that to indicate the ui the form is updated
// then the control flow of the application
} catch (error){
console.error(error)
}
};
One thing I notice over here is you're using POST for the update. Try HTTP PUT instead of POST.
And regarding your answer: You can send modified data in your API call like you're already maintaining the state of the updated data. Then you can just send that row to the API call and handled that in your backend code.
const onSubmitHandler = (e) => {
e.preventDefault();
axios.put("/api/cards/:id", data); // modify the API URL and append dynamic ID of the record.
};

Way to display individual data from MySQL database on React.js?

Is there a way that individual data from the MySQL database will be displayed on the react.js pages, like user profile?
This is my user profile but it display all the data on the database. How I can display single data? For example the information of the Student number 1. const getStudent is where the connection happen from the backend
Front end
import React from "react";
import { useState } from "react";
import Axios from "axios";
import { useNavigate } from "react-router-dom";
function Profile() {
const [studentList, setStudentList] = useState([]);
let navigate = useNavigate();
const getStudent = () => {
Axios.get("http://localhost:3001/students").then((response) => {
setStudentList(response.data);
});
};
return (
<div className="students">
<button onClick={getStudent}>Show Students</button>
<h3>
</h3>
{studentList.map((val, key) => {
return (
<div className="student">
<div>
<h3>Email: {val.email}</h3>
<h3>Password: {val.password}</h3>
<h3>Student Number: {val.student_num}</h3>
<h3>First Name: {val.first_name}</h3>
<h3>Middle Name: {val.middle_name}</h3>
<h3>Last Name: {val.last_name}</h3>
<h3>Year Level: {val.year_lvl}</h3>
<h3>Section: {val.section}</h3>
</div>
</div>
);
})}
</div>
);
}
export default Profile;
key is the name of the column
The connection of the mysql/ BackEnd
app.get("/students", (req, res) => {
db.query("SELECT * FROM student", (err, result) => {
if (err) {
console.log(err);
} else {
res.send(result);
}
});
});

Making an API call in React

I am trying to make an API call in React to return JSON data but I am a bit confused on how to go about this. My API code, in a file API.js, looks like this:
import mockRequests from './requests.json'
export const getRequestsSync = () => mockRequests
export const getRequests = () =>
new Promise((resolve, reject) => {
setTimeout(() => resolve(mockRequests), 500)
})
It is retrieving JSON data formatted like this:
{
"id": 1,
"title": "Request from Nancy",
"updated_at": "2015-08-15 12:27:01 -0600",
"created_at": "2015-08-12 08:27:01 -0600",
"status": "Denied"
}
Currently my code to make the API call looks like this:
import React from 'react'
const API = './Api.js'
const Requests = () => ''
export default Requests
I've looked at several examples and am still a bit confused by how to go about this. If anyone could point me in the right direction, it would be greatly appreciated.
EDIT: In most examples I've seen, fetch looks like the best way to go about it, though I'm struggling with the syntax
Here is a simple example using a live API (https://randomuser.me/)... It returns an array of objects like in your example:
import React from 'react';
class App extends React.Component {
state = { people: [], isLoading: true, error: null };
async componentDidMount() {
try {
const response = await fetch('https://randomuser.me/api/');
const data = await response.json();
this.setState({ people: data.results, isLoading: false });
} catch (error) {
this.setState({ error: error.message, isLoading: false });
}
}
renderPerson = () => {
const { people, isLoading, error } = this.state;
if (error) {
return <div>{error}</div>;
}
if (isLoading) {
return <div>Loading...</div>;
}
return people.map(person => (
<div key={person.id.value}>
<img src={person.picture.medium} alt="avatar" />
<p>First Name: {person.name.first}</p>
<p> Last Name: {person.name.last}</p>
</div>
));
};
render() {
return <div>{this.renderPerson()}</div>;
}
}
export default App;
Does it make sense? Should be pretty straight forward...
Live Demo Here: https://jsfiddle.net/o2gwap6b/
You will want to do something like this:
var url = 'https://myAPI.example.com/myData';
fetch(url).then((response) => response.json())
.then(function(data) { /* do stuff with your JSON data */})
.catch((error) => console.log(error));
Mozilla has extremely good documentation on using fetch here that I highly recommend you read.
The data parameter in the second .then will be an object parsed from the JSON response you got and you can access properties on it by just using the property label as was in the JSON. For example data.title would be "Request from Nancy".
If you are struggling with fetch, Axios has a much simpler API to work with.
Try this in your API.js file (of course install axios first with npm i --save axios):
import axios from 'axios'
import mockRequests from './requests.json'
export const getRequests = (url) => {
if (url) {
return axios.get(url).then(res => res.data)
}
return new Promise((resolve, reject) => { // you need to return the promise
setTimeout(() => resolve(mockRequests), 500)
})
})
In your component, you can access the getRequests function like so
import React, { Component } from 'react'
import { getRequests } from './API.js'
class App extends Component {
state = {
data: null
}
componentWillMount() {
getRequests('http://somedomain.com/coolstuff.json').then(data => {
console.log(data)
this.setState({ data })
})
}
render() {
if (!this.state.data) return null
return (
<div className='App'>
{this.state.data.title}
</div>
)
}
}
export default App