Keep on getting 400 (Bad Request) on a POST request - reactjs

So I'm trying to make a request to a database I have set up. The point is to send a POST to add to the table and for it to feed my back the full list.
I keep on getting "POST http://localhost:8000/api/folders 400 (Bad Request)" in the console. I know it's the POST as when I check the database on both DBeaver and POSTman the database remains the same.
I tried writing '"name"' as 'name' and that didn't change anything.
const postfolder = {
method: 'POST',
body: JSON.stringify({ "name" : f })
};
const getFolder = {
method: 'GET'
};
fetch(`${config.API_ENDPOINT}/folders`, postfolder)
.then(
fetch(`${config.API_ENDPOINT}/folders`, getFolder)
)
.then(res => {
if (!res.ok)
return res.json().then(e => Promise.reject(e))
})
.then(folders => {
this.setState({folders : folders});
})
.catch( error =>{
console.error({ error });
console.log("I fucked up the coding: 001");
});
EDIT:
For clarity here is the component that defines f. Though I did have a console.log (not seen in above) that checks the value and it's giving me the correct one.
import React, {Component} from 'react';
//import { NavLink, Link } from 'react-router-dom'
import './AddFolder.css';
export default class AddFolder extends Component{
handleSubmit = (e) => {
e.preventDefault();
console.log("handleSubmit ran");
var nameError = document.getElementById("folderNameError");
if (!e.target.name.value){
nameError.classList.remove("hidden");
return console.log("no name");
}
nameError.classList.add("hidden");
return this.props.addNewFolder(e.target.name.value);
// process form values here
}
render(){
return (
<form className="folderForm" onSubmit={(e) => this.handleSubmit(e)}>
<h3>New Folder</h3>
<label>Text </label>
<input type="text" className="elementName" name="name" id="folderName"/>
<div>
<button type="submit" className="registration__button">
Save
</button>
</div>
<div>
<button type="reset" className="registration__button">
Cancel
</button>
</div>
<div className="errorSpace">
<p className="hidden" id="folderNameError">A name is required</p>
</div>
</form>
)
}
}
Here's a quick picture of the database. It's just a name and an id.
I'm able to fetch to it using POSTMAN so I don't believe it's the issue.

So I found out that the issue was that I needed to add to my fetch request.
I had it as:
const postfolder = {
method: 'POST',
body: JSON.stringify({ "name" : f })
};
It should be:
const postfolder = {
method: 'POST',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify(newFolder)
};
I needed the content-type.

Related

Django and React: how to redirect to main page after successful login

I am building a login system webapp using react + django. My question is how can I redirect a user towards the main page, if the login credentials are successful.
Right now I only managed to retrieve the authentication token from the backend. How can I modify this class to also check if the login is successful and then redirect towards the main page?
class Login extends Component {
state = {
credentials: {username: '', password: ''}
}
login = event => {
fetch('http://127.0.0.1:8000/auth/', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(this.state.credentials)
})
.then( data => data.json())
.then(
data => {
this.props.userLogin(data.token);
}
)
.catch( error => console.error(error))
}
register = event => {
fetch('http://127.0.0.1:8000/api/users/', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(this.state.credentials)
})
.then( data => data.json())
.then(
data => {
console.log(data.token);
}
)
.catch( error => console.error(error))
}
inputChanged = event => {
const cred = this.state.credentials;
cred[event.target.name] = event.target.value;
this.setState({credentials: cred});
}
render() {
return (
<div>
<h1>Login user form</h1>
<label>
Username:
<input type="text" name="username"
value={this.state.credentials.username}
onChange={this.inputChanged}/>
</label>
<br/>
<label>
Password:
<input type="password" name="password"
value={this.state.credentials.password}
onChange={this.inputChanged} />
</label>
<br/>
<button onClick={this.login}>Login</button>
<button onClick={this.register}>Register</button>
</div>
);
}
}
you need to use hook in react dom router :
please check out this answer , to get more help :
react router doom
but for you id React-Router v6 you can do the following:
import { useNavigate } from "react-router-dom";
navigateIfSuccess() {
let navigate = useNavigate();
// Somewhere in your code, e.g. inside a handler:
navigate("/your-home-page");
}
and in then response you can check if token ? then you can call this function :
like this :
.then(
data => {
if (token)
{
navigateIfSuccess()
}
}

How can we add react js pdf file in firebase realtime database

I am trying to add reactjs pdf file in real time database but my file is not added in firebase. I am shared my code please anyone can help me to solve this issue
my code
import React, { useState } from 'react'
function Demo() {
const [file, setFile] = React.useState("");
function handleUpload(event) {
setFile(event.target.files[0]);
}
const postData = async (e) => {
e.preventDefault();
const result = await fetch('------/data.json', {
method: "POST",
headers: {
"Content-Type": "application/json",
}, body: JSON.stringify({
file
})
})
if (result) {
setFile({file:''})
alert("message send successfull...")
}
} else {
alert("please fill data")
}
}
)
return (
<div>
<div id="upload-box">
<input type="file" onChange={handleUpload} />
<p>Filename: {file.name}</p>
</div>
<button type="button" onClick={postData} className="btn btn-warning" > Submit feedback </button>
</div>
)

Get request with Basic authorization for React js app

I try to do a get request with basic authentication using React JS. I try to do it as follows:
import React,{Component} from 'react';
import { encode } from "base-64";
export class MyDates extends Component{
constructor(props){
super(props);
this.state = {
items:[],
isLoaded:false,
}
}
componentDidMount(){
let url = 'https://gd.xxxxxx.com.tr/api/Dates';
let username = 'xxxxxxx';
let password = 'Bxxxxxxxxx';
fetch(url, {method:'GET', mode: 'no-cors', headers: {'Content-Type': 'application/json','Authorization': 'Basic ' + encode('${username}:${password}')}})
.then(res=>res.json())
.then(json => {
this.setState({
isLoaded:true,
items:json,
})
})
}
render(){
var {isLoaded,items} = this.state;
if(!isLoaded){
return<div>Loading...</div>;
}
else
{
return(
<div className='container'>
<h3>Randevularım sayfası</h3>
<div className='row'>
{items.map(item => (
//item.completed == true ?
<div className='col-md-4 px-4 py-2' key={item.MAHALLEID}>
<div className='m-2 rounded' style={{background:'#e2e2e2'}} >{item.MAHALLE}</div>
</div>
//:null
))};
</div>
</div>
)
}
}
}
Api, user and password checked.
I get the following error:
Failed to load resource: the server responded with a status of 401 ()
MyDates.js:19 Uncaught (in promise) SyntaxError: Unexpected end of input (at MyDates.js:19:1)
at MyDates.js:19:1
enter image description here
could you please try this. I hope this works.
componentDidMount(){
let url = 'https://gd.xxxxxx.com.tr/api/Dates';
let username = 'xxxxxxx';
let password = 'Bxxxxxxxxx';
const base64encodedData = Buffer.from(`${username}:${password}`).toString('base64');
fetch(url, {method:'GET', mode: 'no-cors', headers: {'Content-Type': 'application/json','Authorization': `Basic ${base64encodedData}`}})
.then(res=>res.json())
.then(json => {
this.setState({
isLoaded:true,
items:json,
})
})
}

how to fetch and display API content Onsubmit

I am developing a weather forecast app using Reactjs but i'm having a hard time Fetching/displaying API data
I know this question might have a duplicate but i have looked up all related problems/solutions on this platform and elsewhere but none solved my problem
//const API;
class WeatherApp extends React.Component{
constructor(props){
super(props);
this.state = {
location: "",
reports:[]
}
}
//functions should be written outside the constructor method
onSubmit = event => {
//prevents default loading of the page when this function "onSubmit"
//is called
event.preventDefault();
//saving the value of the textbox to a variable/const
if(this.searchbox.value !== ""){
const searchResult = this.searchbox.value;
//update the state object
this.setState({
location: searchResult + " weather report"
});
}else{
alert("please ensure that field is not empty!");
return;
}
};
componentDidMount(){
if(this.searchbox.value !== ""){
fetch(`api.openweathermap.org/data/2.5/forecast?q=london,uk ${/*this.searchbox.value +*/ KEY}`,{
method: "GET",
dataType: "JSON",
headers: {
"Content-Type": "application/json; charset=utf-8",
}
})
.then(response => { response.json() })
.then(data => {
console.log(data);
this.setState({ reports: data.list})
});
}
}
render(){
return(
<div className="weather-app">
<WeatherAppHeader />
<div className="weather-body">
<div className="entry-pane">
<form onSubmit ={this.onSubmit} >
<input
type="text"
id="search-box"
placeholder="Location e.g Abuja, NG"
size="40"
ref={input => this.searchbox = input} />
<button type="submit" id="search-btn">search</button>
</form>
</div>
<SearchedLocation location={this.state.location} />
<WeatherReport reports={this.state.reports} />
</div>
</div>
);
}
}
const WeatherAppHeader = () => (
<nav> WEATHER FORECAST </nav>
);
const SearchedLocation = ({location}) => (
<div className="searched-loc">{location}</div>
);
SearchedLocation.propTypes = {
location: PropTypes.string
}
///Declaring state within the WeatherReport component
const WeatherReport = ({reports}) => (
<div className="weather-report" >
<ul className="report-list">
{reports.map(report => (
<li key={report.id} className="daily-report">
<span className="daily-report-day">{report.day}</span><br/>
<span className="daily-report-icon">{report.icon}</span><br/>
<span className="daily-report-temp">{report.main.temp}</span>
</li>
))}
</ul>
</div>
);
WeatherReport.propTypes = {
report: PropTypes.array
}
ReactDOM.render(<WeatherApp />, document.getElementById('root'));
i want to display all data from the API on the browser console when the form is submitted but to no avail...and theres no error message. pls can anyone help?
After your fetch call, you are not correctly returning the response when you do .then(response => { response.json() }). Just remove the curly-braces, that way you do an implicit return. Otherwise, if you use curly-braces you must explicitly write .then(response => { return response.json() })
Working code:
componentDidMount(){
if(this.searchbox.value !== ""){
fetch(`api.openweathermap.org/data/2.5/forecast?q=london,uk ${/*this.searchbox.value +*/ KEY}`,{
method: "GET",
dataType: "JSON",
headers: {
"Content-Type": "application/json; charset=utf-8",
}
})
.then(response => response.json())
.then(data => {
console.log(data);
this.setState({ reports: data.list})
});
}
}

React.js, how to send a multipart/form-data to server

We want to send an image file as multipart/form to the backend, we try to use html form to get file and send the file as formData, here are the codes
export default class Task extends React.Component {
uploadAction() {
var data = new FormData();
var imagedata = document.querySelector('input[type="file"]').files[0];
data.append("data", imagedata);
fetch("http://localhost:8910/taskCreationController/createStoryTask", {
mode: 'no-cors',
method: "POST",
headers: {
"Content-Type": "multipart/form-data"
"Accept": "application/json",
"type": "formData"
},
body: data
}).then(function (res) {
if (res.ok) {
alert("Perfect! ");
} else if (res.status == 401) {
alert("Oops! ");
}
}, function (e) {
alert("Error submitting form!");
});
}
render() {
return (
<form encType="multipart/form-data" action="">
<input type="file" name="fileName" defaultValue="fileName"></input>
<input type="button" value="upload" onClick={this.uploadAction.bind(this)}></input>
</form>
)
}
}
The error in backend is "nested exception is org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request; nested exception is java.io.IOException: org.apache.tomcat.util.http.fileupload.FileUploadException: the request was rejected because no multipart boundary was found".
After reading this, we tried to set boundary to headers in fetch:
fetch("http://localhost:8910/taskCreationController/createStoryTask", {
mode: 'no-cors',
method: "POST",
headers: {
"Content-Type": "multipart/form-data; boundary=AaB03x" +
"--AaB03x" +
"Content-Disposition: file" +
"Content-Type: png" +
"Content-Transfer-Encoding: binary" +
"...data... " +
"--AaB03x--",
"Accept": "application/json",
"type": "formData"
},
body: data
}).then(function (res) {
if (res.ok) {
alert("Perfect! ");
} else if (res.status == 401) {
alert("Oops! ");
}
}, function (e) {
alert("Error submitting form!");
});
}
This time, the error in backend is: Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause
Do we add the multipart boundary right? Where should it be?
Maybe we are wrong at first because we don't get the multipart/form-data. How can we get it correctly?
We just try to remove our headers and it works!
fetch("http://localhost:8910/taskCreationController/createStoryTask", {
mode: 'no-cors',
method: "POST",
body: data
}).then(function (res) {
if (res.ok) {
alert("Perfect! ");
} else if (res.status == 401) {
alert("Oops! ");
}
}, function (e) {
alert("Error submitting form!");
});
Here is my solution for image upload with preview through axios.
import React, { Component } from 'react';
import axios from "axios";
React Component Class:
class FileUpload extends Component {
// API Endpoints
custom_file_upload_url = `YOUR_API_ENDPOINT_SHOULD_GOES_HERE`;
constructor(props) {
super(props);
this.state = {
image_file: null,
image_preview: '',
}
}
// Image Preview Handler
handleImagePreview = (e) => {
let image_as_base64 = URL.createObjectURL(e.target.files[0])
let image_as_files = e.target.files[0];
this.setState({
image_preview: image_as_base64,
image_file: image_as_files,
})
}
// Image/File Submit Handler
handleSubmitFile = () => {
if (this.state.image_file !== null){
let formData = new FormData();
formData.append('customFile', this.state.image_file);
// the image field name should be similar to your api endpoint field name
// in my case here the field name is customFile
axios.post(
this.custom_file_upload_url,
formData,
{
headers: {
"Authorization": "YOUR_API_AUTHORIZATION_KEY_SHOULD_GOES_HERE_IF_HAVE",
"Content-type": "multipart/form-data",
},
}
)
.then(res => {
console.log(`Success` + res.data);
})
.catch(err => {
console.log(err);
})
}
}
// render from here
render() {
return (
<div>
{/* image preview */}
<img src={this.state.image_preview} alt="image preview"/>
{/* image input field */}
<input
type="file"
onChange={this.handleImagePreview}
/>
<label>Upload file</label>
<input type="submit" onClick={this.handleSubmitFile} value="Submit"/>
</div>
);
}
}
export default FileUpload;
The file is also available in the event:
e.target.files[0]
(eliminates the need for document.querySelector('input[type="file"]').files[0];)
uploadAction(e) {
const data = new FormData();
const imagedata = e.target.files[0];
data.append('inputname', imagedata);
...
Note:
Use console.log(data.get('inputname')) for debugging, console.log(data) will not display the appended data.
https://muffinman.io/uploading-files-using-fetch-multipart-form-data/ worked best for me. Its using formData.
import React from "react";
import logo from "./logo.svg";
import "./App.css";
import "bootstrap/dist/css/bootstrap.min.css";
import Button from "react-bootstrap/Button";
const ReactDOM = require("react-dom");
export default class App extends React.Component {
constructor(props) {
super(props);
this.test = this.test.bind(this);
this.state = {
fileUploadOngoing: false
};
}
test() {
console.log(
"Test this.state.fileUploadOngoing=" + this.state.fileUploadOngoing
);
this.setState({
fileUploadOngoing: true
});
const fileInput = document.querySelector("#fileInput");
const formData = new FormData();
formData.append("file", fileInput.files[0]);
formData.append("test", "StringValueTest");
const options = {
method: "POST",
body: formData
// If you add this, upload won't work
// headers: {
// 'Content-Type': 'multipart/form-data',
// }
};
fetch("http://localhost:5000/ui/upload/file", options);
}
render() {
console.log("this.state.fileUploadOngoing=" + this.state.fileUploadOngoing);
return (
<div>
<input id="fileInput" type="file" name="file" />
<Button onClick={this.test} variant="primary">
Primary
</Button>
{this.state.fileUploadOngoing && (
<div>
<h1> File upload ongoing abc 123</h1>
{console.log(
"Why is it printing this.state.fileUploadOngoing=" +
this.state.fileUploadOngoing
)}
</div>
)}
</div>
);
}
}
React File Upload Component
import { Component } from 'react';
class Upload extends Component {
constructor() {
super();
this.state = {
image: '',
}
}
handleFileChange = e => {
this.setState({
[e.target.name]: e.target.files[0],
})
}
handleSubmit = async e => {
e.preventDefault();
const formData = new FormData();
for (let name in this.state) {
formData.append(name, this.state[name]);
}
await fetch('/api/upload', {
method: 'POST',
body: formData,
});
alert('done');
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<input
name="image"
type="file"
onChange={this.handleFileChange}>
</input>
<input type="submit"></input>
</form>
)
}
}
export default Upload;
the request was rejected because no multipart boundary was found".
When you send multipart/form-data, the boundary is automatically added to a content-type of a request header. you have to tell the server when the parameter ends with the boundary rule. You had to set the Content-type like this
"Content-Type": `multipart/form-data: boundary=add-random-characters`
This article with guide you: https://roytuts.com/boundary-in-multipart-form-data/
The boundary is included to separate name/value pair in the
multipart/form-data. The boundary parameter acts like a marker for
each pair of name and value in the multipart/form-data. The boundary
parameter is automatically added to the Content-Type in the http
(Hyper Text Transfer Protocol) request header.
For sending multipart/formdata, you need to avoid contentType, since the browser automatically assigns the boundary and Content-Type.
In your case by using fetch, even if you avoid Content-Type it sets to default text/plain. So try with jQuery ajax. which removes the contentType if we set it to false.
This is the working code
var data = new FormData();
var imagedata = document.querySelector('input[type="file"]').files[0];
data.append("data", imagedata);
$.ajax({
method: "POST",
url: fullUrl,
data: data,
dataType: 'json',
cache: false,
processData: false,
contentType: false
}).done((data) => {
//resolve(data);
}).fail((err) => {
//console.log("errorrr for file upload", err);
//reject(err);
});

Resources