React redux upload image with graphql and use of axios - reactjs

When I try to upload image i getting an error:
xhr.js:177 POST http://localhost:3000/graphql 400 (Bad Request)
categoryAction.tsx:57 Error: Request failed with status code 400
at createError (createError.js:16)
at settle (settle.js:17)
at XMLHttpRequest.handleLoad (xhr.js:62)
When I upload From the postman upload successfuly but when try with react axios getting above error
My Form
const addForm = (props:any) => {
const [category,setCategory] = useState({
image:''
})
const onDataChange = (e:any,name:string,image:string) => {
let oldData : any = { ...category }
const imageFile = e.target.files[0];
oldData[image] = imageFile;
setCategory(oldData);
}
const onFinish = async (values : any) => {
let categoryData = {...category}
let formdata = new FormData();
formdata.append('image',categoryData.image);
await props.AddCategory(formdata);
console.log('Success:', values);
};
return (
<>
<Form>
<Form.Item
name="image"
label="Category Image"
>
<Input type="file" name="image" onChange={(e) => onDataChange(e,'image','image')} />
</Form.Item>
<Button type="primary" htmlType="submit" onClick={onFinish}> Submit </Button>
</Form>
</>
}
const mapDispatchToProps = (dispatch:any) => {
return {
AddCategory:(data:any) => dispatch(AddCategory(data))
}
export default connect(null,mapDispatchToProps)(addForm);
Now this is my Redux Action
export const AddCategory : any = (data:any) => {
return async (dispatch: Dispatch) => {
dispatch({
type:types.INIT_ADD_DATA
})
await axios.post(`http://localhost:3000/graphql`,
{
query: ` mutation {
addCategory(image: ${data}){
imagePath
}
}
`
})
.then((response) => {
dispatch({
type:types.ADD_DATA_SUCCESS,
myData: { data : response.data}
});
}).catch((error) => {
console.log(error)
dispatch({
type:types.ADD_DATA_FAILED,
error:error.message
});
})
};
};
My API IN Node Is
import { gql } from 'apollo-server'
const CategoriesTypeDef = gql`
extend type Mutation {
addCategory(image: Upload!): Category!
}
type Category {
categoryId: ID!
image: String!
}
`
while api through post data , data uploaded successfully but use of react typescript axios it will generate error how to fix it .

Related

ReactJS ReactQuill gives "Uncaught TypeError: Cannot read properties of undefined (reading 'name')"

I am programming a ReactJS application where the user should be able to edit email templates. The email template has a title and a text. The text should be WYSIWYG. I picked React Quill as a text editor, which I am trying to implement now. In the code below I have removed code like for example authentication to make it easier to read here on Stack Overflow.
Error
When adding this I get an error at EmailTemplateEdit.js:60:1:
Uncaught TypeError: Cannot read properties of undefined (reading 'name')
at Object.handleChange [as onChange] (EmailTemplateEdit.js:60:1)
at ReactQuill.onEditorChangeText (index.tsx:533:1)
at ReactQuill._this.onEditorChange (index.tsx:498:1)
at Emitter.emit (quill.js:8671:1)
at Emitter.emit (quill.js:1943:1)
at Quill.modify (quill.js:1674:1)
at Quill.setContents (quill.js:1505:1)
at ReactQuill.setEditorContents (index.tsx:387:1)
at ReactQuill.shouldComponentUpdate (index.tsx:230:1)
at checkShouldComponentUpdate (react-dom.development.js:14134:1)
Line 60 corresponds to a const which handles changes in the form:
// Form data .changed
const handleChange = e => {
setData({
...data,
[e.target.name]: e.target.value
});
};
JSON from backend
{
"template_cloud_name":"Azure",
"template_id":2,
"template_language":"ENG",
"template_text":"<p>Hello</p>\n\n<p>\n<b>Due to changes</b></p>\n",
"template_title":"Request for permissions",
"template_when_to_send":"new_users"
}
EmailTemplateEdit.js
import { useContext, useEffect, useState } from "react";
import { useParams } from 'react-router-dom';
import ReactQuill from 'react-quill';
import 'react-quill/dist/quill.snow.css';
export function EmailTemplateEdit() {
// Get ID from url
const { templateId } = useParams();
// Data
const [data, setData] = useState({
template_id: templateId,
template_title: '',
template_language: '',
template_cloud_name: '',
template_when_to_send: '',
template_text: ''
});
// Update email template
const handleSubmit = async (e) => {
e.preventDefault();
let result = await fetch("https://localhost:5001/api/email_templates/put_email_template", {
method: "POST",
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data),
});
let resultJson = await result.json();
let resultMessage = resultJson['message']
let resulData = resultJson['data']
let resultError = resultJson['error']
};
// Form data .changed
const handleChange = e => {
setData({
...data,
[e.target.name]: e.target.value
});
};
// Load data
const loadData = async (e) => {
let result = await fetch("https://localhost:5001/api/email_templates/get_email_template?template_id=" + templateId, {
method: "GET",
headers: {
}
});
let resultJson = await result.json();
setData(resultJson)
};
// On load
useEffect(() => {
// Loading
loadData()
}, []);
return (
<div>
<h1>Edit email template</h1>
{/* Form */}
<form onSubmit={handleSubmit} id="form">
<p>Title<br />
<input type="text" name="template_title" value={data.template_title} onChange={handleChange} style={{minWidth: "50%"}} /></p>
<ReactQuill theme="snow" name="template_text" value={data.template_text} onChange={handleChange} />
<p><button>Submit</button></p>
</form>
</div>
);
}
export default EmailTemplateEdit;
Question
How can I handle changes to ReactQuill in handleChange?

How to take input in front-end and send request to back-end?

I am working on a basic blog application and it takes title and post input
I am trying to take two inputs and send the request to add them to the database.
The request is made when the user submits the form.
import React, { useState } from "react";
import axios from "axios";
const CreatePost = () => {
const [title, setTitle] = useState("");
const [post, setPost] = useState("");
const onChangeTitle = (e) => {
setTitle(e.target.value);
};
const onChangePost = (e) => {
setPost(e.target.value);
};
const onSubmit = (e) => {
e.preventDefault();
const newPost = {
title: title,
post: post,
};
console.log(newPost);
axios("http://localhost:5000/add", newPost)
.then((res) => console.log(res.data))
.catch((err) => console.log(err));
};
return (
<form onSubmit={onSubmit} className="container">
<div className="mb-3">
<label className="form-label">Title</label>
<input onChange={onChangeTitle} className="form-control"></input>
</div>
<div className="mb-3">
<label className="form-label">Write Post</label>
<textarea
onChange={onChangePost}
className="form-control"
rows="15"
></textarea>
</div>
<button type="submit">POST</button>
</form>
);
};
export default CreatePost;
The post request to add the content is:
app.post("/add", (req, res) => {
const title = req.body.title;
const post = req.body.post;
const newPost = new Post({ title, post });
newPost
.save()
.then(() => res.json("Post added"))
.catch((err) => res.status(400).json("Error:" + err));
});
Error:
GET http://localhost:5000/add 404 (Not Found)
AxiosError {message: 'Request failed with status code 404', name: 'AxiosError', code: 'ERR_BAD_REQUEST', config: {…}, request: XMLHttpRequest, …}
You're sending a GET request:
GET http://localhost:5000/add 404 (Not Found)
But the server-side code is expecting a POST request:
app.post("/add", (req, res) => {
Send a POST request instead:
axios.post("http://localhost:5000/add", newPost)

How to fix 'error - unhandledRejection: TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received undefined'

I have a task for uploading images using Next js. API for image uploading has been given and it exists in the same project and when it becomes successful images are stored in a separate directory.
API for image uploading is as follows,
import formidable from "formidable";
import path from "path";
import { renameSync } from "fs";
export const config = {
api: {
bodyParser: false,
},
};
export default async function upload(req, res) {
if (req.method !== "POST") {
return res.status(405).json({ error: "Method not allowed" });
}
const form = new formidable.IncomingForm({
keepExtensions: true,
maxFileSize: 200 * 1024 * 1024,
});
return new Promise((resolve, reject) => {
form.parse(req, async (err, fields, files) => {
if (err) {
res.status(500).json({ error: err.message });
return resolve();
}
if (!files.image) {
res.status(422).json({ error: "Bad request: missing image field" });
return resolve();
}
const ext = path.extname(files.image.path);
const uuid = Math.random().toString(26).slice(2);
await renameSync(files.image.path, `./public/images/${uuid}${ext}`);
res.status(201).json({
uuid,
url: `/images/${uuid}${ext}`,
});
return resolve();
});
});
}
Code for the front-end is mentioned below,
import React from "react";
export default function UploadImage() {
const [imgsSrc, setImgsSrc] = React.useState([]);
const uploadToClient = (e) => {
for (const file of e.target.files) {
setImgsSrc((imgs) => [...imgs, file]);
}
};
const uploadToServer = async () => {
let formData = new FormData();
for (const file of imgsSrc) {
formData.append('image', file, file.name)
}
const response = await fetch("/api/upload", {
method: "POST",
body: formData
});
};
return(
<div>
<h3>Upload photos</h3>
<input onChange={uploadToClient} type="file" name="file" multiple />
<div>
{imgsSrc.map((link) => (
<img src={link} style={{ width: 200, height: 200 }} />
))}
</div>
<button type="submit" onClick={uploadToServer}>Send to server</button>
</div>
)
}
When uploading images I am getting 'error - unhandledRejection: TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received undefined'.
Any suggestion would be highly appreciated!

Upload multiple images to separate folder in Next Js [duplicate]

I have a task for uploading images using Next js. API for image uploading has been given and it exists in the same project and when it becomes successful images are stored in a separate directory.
API for image uploading is as follows,
import formidable from "formidable";
import path from "path";
import { renameSync } from "fs";
export const config = {
api: {
bodyParser: false,
},
};
export default async function upload(req, res) {
if (req.method !== "POST") {
return res.status(405).json({ error: "Method not allowed" });
}
const form = new formidable.IncomingForm({
keepExtensions: true,
maxFileSize: 200 * 1024 * 1024,
});
return new Promise((resolve, reject) => {
form.parse(req, async (err, fields, files) => {
if (err) {
res.status(500).json({ error: err.message });
return resolve();
}
if (!files.image) {
res.status(422).json({ error: "Bad request: missing image field" });
return resolve();
}
const ext = path.extname(files.image.path);
const uuid = Math.random().toString(26).slice(2);
await renameSync(files.image.path, `./public/images/${uuid}${ext}`);
res.status(201).json({
uuid,
url: `/images/${uuid}${ext}`,
});
return resolve();
});
});
}
Code for the front-end is mentioned below,
import React from "react";
export default function UploadImage() {
const [imgsSrc, setImgsSrc] = React.useState([]);
const uploadToClient = (e) => {
for (const file of e.target.files) {
setImgsSrc((imgs) => [...imgs, file]);
}
};
const uploadToServer = async () => {
let formData = new FormData();
for (const file of imgsSrc) {
formData.append('image', file, file.name)
}
const response = await fetch("/api/upload", {
method: "POST",
body: formData
});
};
return(
<div>
<h3>Upload photos</h3>
<input onChange={uploadToClient} type="file" name="file" multiple />
<div>
{imgsSrc.map((link) => (
<img src={link} style={{ width: 200, height: 200 }} />
))}
</div>
<button type="submit" onClick={uploadToServer}>Send to server</button>
</div>
)
}
When uploading images I am getting 'error - unhandledRejection: TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received undefined'.
Any suggestion would be highly appreciated!

Delete item from MongoDB using React, Redux and Express

I'm trying to delete an order line from my MongoDB database using React, Redux and Express/Node but I'm getting the following error in my console:
VM118:1 DELETE http://localhost:3000/api/meals/:id/jp4PaZve3 404 (Not Found)
I'm not sure why it's pointing to port 3000, when my local server is running on 5000?
In my server file, I have the following delete endpoint created in Express
app.delete("/api/meals/:id", async (req, res) => {
const deletedMeal = await Meal.findByIdAndDelete(req.params.id);
res.send(deletedMeal);
});
In my redux actions I have the following (I'm not sure if this is correct):
export const deleteMeal = (id) => async (dispatch) => {
await fetch("/api/meals/:id/" + id, {
method: "DELETE",
});
dispatch({
type: DELETE_MEAL,
payload: id,
});
};
My UpdateMenu screen is as follows:
import React, { Component } from "react";
import { connect } from "react-redux";
import { fetchMeals, deleteMeal } from "../actions/mealActions";
class UpdateMenuScreen extends Component {
constructor(props) {
super(props);
this.state = {
meal: null,
};
}
componentDidMount() {
this.props.fetchMeals();
}
deleteMeal(id) {
this.props.deleteMeal(id);
}
render() {
return (
<div>
<h3>Current Menu</h3>
{!this.props.meals ? (
<div>Loading...</div>
) : (
<ul className="meals">
{this.props.meals.map((meal) => (
<li key={meal._id}>
<div className="meal">
<p>{meal.title}</p>
<button
className="button"
onClick={() => this.props.deleteMeal(meal._id)}
>
Delete
</button>
</div>
</li>
))}
</ul>
)}
<button>Add New Menu Item</button>
</div>
);
}
}
export default connect((state) => ({ meals: state.meals.items }), {
fetchMeals,
deleteMeal,
})(UpdateMenuScreen);
When I try and run my delete method in Postman however, it doesn't work. Can anyone see what I'm doing wrong?
In your deleteMeal action, you have to put the id in the URL dynamically with template strings,
await fetch("/api/meals/:id/" + id
1) it's equal to /api/meals/:id/id but according to your backend it should be /api/meals/:id
2) and you have to put the whole URL like http://localhost:5000/api/meals/${id} cause if you don't put the base, it will do a request on the port of your client so 3000
///////
So instead of :
export const deleteMeal = (id) => async (dispatch) => {
await fetch("/api/meals/:id/" + id, {
method: "DELETE",
});
dispatch({
type: DELETE_MEAL,
payload: id,
});
};
try this :
export const deleteMeal = (id) => async (dispatch) => {
await fetch(`http://localhost:5000/api/meals/${id}/`, {
method: "DELETE",
});
dispatch({
type: DELETE_MEAL,
payload: id,
});
};

Resources