React - Post Request does not work on mobile - reactjs

I'm trying to submit some simple data to my server. Everything works fine - on my desktop. When i try on my mobile (same network) it does not work. The page just refreshes but the POST request fails (not sure if it fails because i can't open a console on my mobile). It seems like the page refreshes before it actually gets to the fetch command but i'm not sure and not sure how to troubleshoot because it is working fine on my desktop. Please help! Thanks :)
const onSubmit = (event) => {
const data = {
price: price,
gallons: gallons,
miles: miles,
notes: notes,
source: params.car_source,
};
const options = {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
};
fetch(`${process.env.REACT_APP_API_BASE_URL}/consumption/`, options);
};

This will work! Try this out, Just added event.preventDefault() in handleSubmit function.
I follow this link for Debugging in mobile.
import React, { useState } from 'react';
function NameForm() {
const [name, setName] = useState('');
const handleSubmit = (event) => {
event.preventDefault();
const data = {
price,
gallons,
miles,
notes,
source: params.car_source,
};
const options = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
};
fetch(`${process.env.REACT_APP_API_BASE_URL}/consumption/`, options);
};
const handleChange = (event) => {
setName(event.target.value);
};
return (
<form onSubmit={handleSubmit}>
<label>
Name:
<input type="text" value={name} onChange={handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
export default NameForm;

Related

Changing form input data before POST request

I'm working with a reactjs frontend and springboot backend and I'm wondering how I can format/change form input data before I make a POST request to my backend. I'd like to maintain the dateFormat when displayed, but I'd like to change the value of the date to an ISO string before I make the POST request. New to react, so any discussion / help is appreciated.
import "./styles.css";
import DatePicker from 'react-datepicker';
import {useForm, Controller} from "react-hook-form";
import "react-datepicker/dist/react-datepicker.css";
export default function App() {
const {register, formState: { errors }, handleSubmit, control} = useForm();
const onSubmit = (data) => {
console.log(data.time.toISOString());
fetch('/test',
{ method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(data),
}
);
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<Controller
name="time"
control={control}
render={({ field: { onChange, value} }) => (
<DatePicker
onChange = {onChange}
selected= {value}
showTimeSelect
dateFormat="MMM d, yyyy h:mm aa"
/>
)}
rules={{ required:true}}
/>
<input type="submit"/>
</form>
);
}
You're so close! Instead of just logging the transformed data, submit it as part of your post request:
const onSubmit = (data) => {
const transformedTime = data.time.toISOString();
// make a copy of data, but overwrite the time property with our transformed time
const dataToSubmit = { ...data, time: transformedTime };
// submit the new dataToSubmit object as a part of the request
fetch('/test',
{ method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(dataToSubmit),
}
);
};

Struggling with PUT request

I'm on React for 2 months, and still struggling with CRUD operations such as EDIT.
I've been trying couple different ways, but every time I send nothing to my API.
I do not manage to grab the information correctly in order to push it to the server.
The route is working with Postman, there are no issues there, it's only React and me ^^.
I would be grateful if someone could read my code and tell me where the problem might come from, thanks !
1st try
const usernamelEl = React.useRef(null)
const timezoneEl = React.useRef(null)
const handleEditProfile = async () => {
const creds = {
user: {
username: usernameEl.current.value,
timezone: timezoneEl.current.value
}
};
const config = {
method: 'PUT',
headers: {
Accept: "application/json",
"Content-Type": "application/json",
"Authorization": `Bearer ${Cookies.get('token')}`
},
body: JSON.stringify(creds)
};
const res = await fetch(`${process.env.REACT_APP_API_URL}api/users/${id}`, config);
const user = await res.json();
console.log(user)
}
return (
<form onSubmit={handleEditProfile} className="form">
<div className="input-group">
<label htmlFor="username">username</label>
<input type="text" id="username" ref={usernameEl}/>
</div>
<div className="input-group">
<label htmlFor="timezone">timezone</label>
<input type="text" id="timezone" ref={timezoneEl}/>
</div>
<div className="input-group">
<SubmitButtonComponent type="submit">
Submit
</SubmitButtonComponent>
</div>
</form>
)
2nd try
const [usernameEl, setUsernameEl] = useState('')
const [timezoneEl, setTimezoneEl] = useState('')
const handleChangeUsername = e => {
setUsernameEl(e.target.value)
}
const handleChangeTimezone= e => {
setTimezoneEl(e.target.value)
}
const handleEditProfile = async (e) => {
const creds = {
user: {
username: usernameEl,
timezone: timezoneEl
}
};
const config = {
method: 'PUT',
headers: {
Accept: "application/json",
"Content-Type": "application/json",
"Authorization": `Bearer ${Cookies.get('token')}`
},
body: JSON.stringify(creds)
};
const res = await fetch(`${process.env.REACT_APP_API_URL}api/users/${id}`, config);
const data = await res.json();
console.log(data)
try {
setUsernameEl('')
setTimezoneEl('')
}
catch(err) {
console.log(err)
}
}
return (
<form className="form" onSubmit={handleEditProfile}>
<div className="input-group">
<label htmlFor="username">username</label>
<input type="text" id="username" onChange={handleChangeUsername}/>
</div>
<div className="input-group">
<label htmlFor="timezone">timezone</label>
<input type="text" id="timezone" onChange={handleChangeTimezone}/>
</div>
<SubmitButtonComponent type="submit">
Submit
</SubmitButtonComponent>
</form>
if I ever try to pass a value
const handleEditProfile = async (e) => {
e.preventDefault();
[..]
onSubmit={(e)=>handleEditProfile(e.target.value)}>
or
onSubmit={handleEditProfile(e)>
then I get this error

How to do form post API in react?

I would like to add data to my database through the API url, with a form. But it's not really working. I'm kind of struggling to make it work. When I click on 'add' I check the array but nothing new is being added. I think i'm doing something wrong in the body variable. But not sure. How can i get the values from the form into the url API?
Here is my code:
export function AlbumForm(props) {
const [PostId, setPostId] = useState(0);
const {register, handleSubmit, errors, control} = useForm({
defaultValues: props.album
? props.album
: {
name: "",
artist: "",
imageUrl: "",
},
});
const useCreateAlbum =((data) => {
console.log(data);
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: data,
mode: 'cors'
};
fetch(process.env.REACT_APP_API_URL, requestOptions)
.then(response => response.json())
.then(data => setPostId(data.id));
});
return (
<div className="AlbumForm">
<h2>Album Form</h2>
<form onSubmit={handleSubmit(useCreateAlbum)}>
<input type="text" {...register("name")} placeholder="Name" name="name"/>
<input type="text" {...register("artist")} placeholder="Artist" name="artist" />
<input type="text" {...register("imageUrl")} placeholder="ImageUrl" name="imageUrl"/>
<button type="submit">{props.submitbutton}</button>
</form>
</div>
);
}
never mind I solved it. I just had to do this:
const useCreateAlbum =((data) => {
console.log(data);
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),/////here is the change
mode: 'cors'
};
fetch(process.env.REACT_APP_API_URL, requestOptions)
.then(response => response.json())
.then(data => setPostId(data.id));
});

Rect Post request

I am creating project in React /Django Rest Framework and I want to send Post request. My problem is that I am always sending string and I should send list of int.
My component look like this
const NewLecture = (props) => {
const[ lecture, setLecture] = useState({
title:'',
programs: [],
})
const dispatch = useDispatch()
const history = useHistory()
// console.log('this is history:', history)
const program_id = props.match.params.id;
//event handlers
const newLectureHandler = (event) => {
const{name, value}= event.target
setLecture({
...lecture,
[name]:value
})
};
useEffect(() => {
console.log('mounting in NewLecture');
dispatch(LecturesActions())
dispatch(GetPrograms())
}, [])
const handleSubmit = e =>{
e.preventDefault()
props.close()
dispatch(sendLecture(lecture, program_id, history))
}
const stringtoArray = (arg)=> {
console.log('this is arg', [arg]);
return [arg]
}
return (
<NewGradeStyled>
<div className="new-grade-style">
<h1>Create New Lecture</h1>
<form >
<div className="form-grade">
<label htmlFor="title">Lecture Name</label>
<input type="text" name="title" onChange={newLectureHandler}/>
</div>
<div className="form-grade">
<label htmlFor="programs">Program</label>
{/* <input type="number" name="programs" onChange={newLectureHandler}/> */}
<select name="programs" onChange={newLectureHandler}>
<option > </option>
{props.data ? <option value={props.data.id}>{props.data.name}</option> : ''}
</select>
</div>
<div className="btn-group">
<button className="save" onClick={handleSubmit}>Save</button>
<button onClick={props.close}>Cancle</button>
</div>
</form>
</div>
</NewGradeStyled>
)
}
export default withRouter(NewLecture)
and this is my action
export const sendLecture = (lecture) => (dispatch, getState) => {
const{title, programs} = lecture
const token = getState().token
const config = {
body: JSON.stringify(lecture),
method: "POST",
headers: new Headers({
"Content-Type": "application/json",
"Authorization": `Bearer ${token}`
}),
body: JSON.stringify({title, programs})
};
fetch(`${baseUrl}/backend/api/lectures/new/`, config)
.then((res) => res.json())
.then((data)=>{
console.log('Post lecture action', data)
dispatch({type: 'GET_LECTURE_DATA', payload: data})
});
}
I expect to get this from JSON
{
"title":"some string"
"programs":[1]
}
reducer
const initialState = {
lecture_data:[],
}
export const authReducer = (state = initialState, action) => {
switch (action.type) {
case "GET_LECTURE_DATA": {
const lecture_data = action.payload;
return { ...state, lecture_data };
}
default:
return state;
}
}
If I send it as input type= "number" result is always the same I get error "Expected a list of items but got type "str"."
I donĀ“t kow how I should change it. Do you have any Ideas?
In this part:
const config = {
body: JSON.stringify(lecture),
method: "POST",
headers: new Headers({
"Content-Type": "application/json",
"Authorization": `Bearer ${token}`
}),
body: JSON.stringify({ title, programs })
};
you set the body property twice. Is that intentional?
You write the api expects a list. Did you mean to pass this body: JSON.stringify( [title, programs ]) Although that would send an array of objects of which the first item is title, and the second is programs. Can you clarify what the API expects? And what the structure of title and programs looks like?

Axios when posting to api there isn't a response returned, but the error handling works if there is an error in the URL

I am posting to my API and where it should return a response nothing is logged to the console.
I have the following code:
import React, {useState} from "react"
import axios from 'axios';
const conn = axios.create({
baseURL: 'https://myurl.com',
headers: {
'Content-Type': 'application/json'
}
});
const Login = () => {
const [un,setUn] = useState('');
const [pw,setPw] = useState('');
const pleaseLogin = (un, pw) => {
//Hard coding the values for now
const email = "me#mydomain.org";
const pass = "weakpassword";
conn.post('/apilogin/authenticate/',
{
email: email, password: pass
})
.then(res => {
console.log("This is never reached");
console.log(res);
console.log(res.data);
}, (error) => {
console.log("This is reached if I alter the URL");
console.log(error);
});
}
return (
<form onSubmit={() => pleaseLogin(un,pw)}>
<label>
User Name:
<input type="text" value={un} onChange={setUn} />
</label>
<label>
Password:
<input type="text" value={pw} onChange={setPw} />
</label>
<input type="submit" value="Submit" />
</form>
);
};
export default Login
If I change the URL then I get a 404 error so the error handling is working, but no response is logged at all if the URL is correct. If I run this call to the API through postman, then it works fine and I get a JSON response like below:
{
"refresh": "tokendata",
"access": "tokendata"
}
When trying using fetch, I was seeing CORS errors when logging the response, but since adding the cors setting it stopped, but I am still not seeing a response. There is no error on the server I can see, I just see 200OK when the request is processed.
This is using the Fetch method:
const pleaseLogin = async (un, pw) => {
const data = { email: un, password: pw };
fetch(`${baseUrl}/apilogin/authenticate/`, {
method: 'POST', // or 'PUT'
headers: {
'Content-Type': 'application/json',
},
mode: 'cors',
body: JSON.stringify(data),
})
.then(response => {console.log(response)});
}
I have tried running react from http://localhost:3000 and from http://myipaddress:3000 as well and that hasn't made a difference.
Server logs:
2020-12-03T10:04:37.365435+00:00 heroku[router]: at=info method=POST path="/apilogin/authenticate/" host=OMITTED fwd="myexternalipaddress" dyno=web.1 connect=0ms service=200ms status=200 bytes=761 protocol=https
2020-12-03T10:04:37.363496+00:00 app[web.1]: omitted - - [03/Dec/2020:10:04:37 +0000] "POST /apilogin/authenticate/ HTTP/1.1" 200 438 "http://localhost:3000/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"
UPDATE: modified headers below.
headers: {
'Content-Type': 'application/json',
'Sec-Fetch-Site': 'cross-site',
},
UPDATE: I have tried running the react app on a development server where the API backend runs. The django application is set up to handle CORS. I have tried with Firefox and the server receives a request like below:
OPTIONS /api/authenticate/ HTTP/1.1" 200 0
If I run the app in Chrome then it gets nothing at all. I understand that this is a pre-flight request. As far as I can tell, the server is set up to handle this. I'm not sure where to go from here. I know that other frameworks work with the same request. I have tested with static HTML as below and this works.
<script>
const login = async () => {
const email = "emailaddress";
const pass = "password";
try {
const response = await axios({
'Content-Type' : 'application/json',
url: 'http://127.0.0.1:8000/api/authenticate/',
method: 'post',
data: { email: email, password: pass },
}).then( response => {
console.log(response);
});
} catch (e) {
console.log(e);
}
}
login();
</script>
try add "proxy": "http://localhost:3000" to your package.json inside your client folder (to overcome CORS issues).:-
/client/package.json
{
"name": "proj_name",
"version": "0.1.0",
"proxy": "http://localhost:3000"
}
Then, add async await to your res (a lot of times I do stumble upon this issue & this helps me):-
Login.js:-
import React, {useState} from "react"
import axios from 'axios';
const conn = axios.create({
baseURL: 'https://myurl.com',
headers: {
'Content-Type': 'application/json'
}
});
const Login = () => {
const [un,setUn] = useState('');
const [pw,setPw] = useState('');
const sayHello = () => {
console.log("hello");
}
const pleaseLogin = (un, pw) => {
//Hard coding the values for now
const email = "me#mydomain.org";
const pass = "weakpassword";
conn.post('/apilogin/authenticate/',
{
email: email, password: pass
})
.then(async res => {
const result = await res
console.log("This is never reached");
console.log(result);
console.log(result.data);
}, (error) => {
console.log("This is reached if I alter the URL");
console.log(error);
});
}
return (
<form onSubmit={() => pleaseLogin(un,pw)}>
<label>
User Name:
<input type="text" value={un} onChange={setUn} />
</label>
<label>
Password:
<input type="text" value={pw} onChange={setPw} />
</label>
<input type="submit" value="Submit" />
</form>
);
};
export default Login
I don't quite understand when you stated it works with static HTML in your updates above.
I seems like these part of code (show below) might have contribute to your issue:-
// this part
const conn = axios.create({
baseURL: 'https://myurl.com',
headers: {
'Content-Type': 'application/json'
}
});
// and this part
conn.post('/apilogin/authenticate/',
{
email: email, password: pass
})
.then(res => {
console.log("This is never reached");
console.log(res);
console.log(res.data);
}, (error) => {
console.log("This is reached if I alter the URL");
console.log(error);
});
If you build your axios around that cause of wanting it to be dynamic. Then you could change it to your own static HTML updates (which I think can also can be dynamic with some changes):-
Login.js:-
import React, {useState} from "react"
import axios from 'axios';
const baseUrl = 'https://myurl.com'
const config = {
headers: {
'Content-Type': 'application/json'
}
}
const Login = () => {
const [un,setUn] = useState('');
const [pw,setPw] = useState('');
const sayHello = () => {
console.log("hello");
}
const pleaseLogin = async(un, pw) => {
//Hard coding the values for now
const email = "me#mydomain.org";
const pass = "weakpassword";
// the BASEURL & CONFIG can still be DYNAMIC
await axios.post(baseUrl + '/apilogin/authenticate/',
{
email: email, password: pass
}, config)
.then(async res => {
const result = await res
console.log("This is never reached");
console.log(result);
console.log(result.data);
})
.catch(error => {
console.log("This is reached if I alter the URL");
console.log(error);
});
}
return (
<form onSubmit={() => pleaseLogin(un,pw)}>
<label>
User Name:
<input type="text" value={un} onChange={setUn} />
</label>
<label>
Password:
<input type="text" value={pw} onChange={setPw} />
</label>
<input type="submit" value="Submit" />
</form>
);
};
export default Login

Resources