I am a beginner in both React and Spring Boot and I realized how this might be a really easy question, but I had a problem in understanding how to handle PUT requests in React. I have a form as the following:
<Form onSubmit={this.handleSubmit}>
<FormGroup>
<Label>Description</Label>
<Input type="text" name="description" onChange={this.handleChange}/>
</FormGroup>
<FormGroup>
<Label>Category</Label>
<select onChange={this.handleChangeCategory}>{optionList}</select>
</FormGroup>
<FormGroup>
<Label>Date</Label>
<DatePicker selected={this.state.item.timeStamp} onChange={this.handleChangeDate}/>
</FormGroup>
</Form>
This is the item object in the state:
item: {
timeStamp: new Date(),
description: ''
category: {id: '', categoryName: ''}
}
And I have an "update" button as the following:
expenses.map (expense =>
<Button size="sm" color="secondary" onClick={ () => this.update(expense.id)}>Update</Button>
The update() is as following:
async update(id) {
// I want to populate the form with the data from expense.id the user clicked on
const response = await fetch(`/api/expenses/${id}`); // GET endpoint from Spring Boot
const body = await response.json();
this.setState( {item: body});
// Handling PUT request
await fetch(`api/expenses/${id}`, {
method: 'PUT',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
});
updatedItem = {...this.state.item}; // Getting the updated item
this.setState({item: updatedItem}); // I want to be able to update the state like this
this.props.history.push('/expense');
}
I want to be able to populate the form with the data from the expense.id the user clicked on and I had the logic of getting the GET method from the endpoint in Spring Boot but it did not work. I am also confused on how handle the PUT request after the user updated the form. Sorry if it is a stupid question. Any help would be appreciated, thanks alot!
Related
I am having difficulty understanding what I'm doing wrong on this POST request. The POST request itself is working which I confirmed in the network tab.
However, I am only able to post static values that I define, rather than the values from the form fields. Please have a look. This is driving me up the wall. Thank you!
Notes:
In TestForm.js it doesn't actually seem to console.log the response as I'm asking it to.
I receive no errors.
This does POST to my server, and into Postgres, and I will show below what that looks like when I console.log.
console.log(sauces) at the start of HandleSubmit does in fact show "sauces" currectly, which is whatever is input into the first form field.
GitHub Repository
The React Form Component (TestForm.js):
function TestForm() {
const [sauce, setSauce] = useState('');
const [presentation, setPresentation] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
fetch('http://jyh:3000', {
method: 'POST',
headers: {'Content-Type':'application/json'},
body: JSON.stringify({
"test_name": sauce,
"test_sauce": presentation,
}),
}).then((res) => {
console.log(res.json());
return res.json();
}).catch((err) => {
console.log(err.message);
});
};
return (
<form onSubmit={handleSubmit}>
<div className="color-section" id="reviewASauce">
<div className="container-fluid">
<h2>Review a Sauce</h2><br />
Trying a sauce that is already in our database? Review it!
<br />
<br />
<br />
<h2>Sauce Name</h2>
<Form.Label htmlFor="test_name">
</Form.Label>
<Form.Control
type="text"
id="test_name"
aria-describedby="test_name"
placeholder="Input the name of the sauce here."
value={sauce}
onChange={(e) => setSauce(e.target.value)}
/>
<Form.Text id="test_name" muted>
</Form.Text>
<br />
<br />
<Form.Label htmlFor="test_sauce">
</Form.Label>
<Form.Control
type="text"
id="test_sauce"
aria-describedby="test_sauce"
placeholder="Input the name of the sauce here."
value={presentation}
onChange={(e) => setPresentation(e.target.value)}
/>
<Form.Text id="test_sauce" muted>
</Form.Text>
<br />
<br />
<Button variant="dark" type="submit">
Submit
</Button>
</div>
</div>
</form>
);
}
export default TestForm;
Server index.js:
app.post('/', async (req, res) => {
await TestTable.create({
test_name: "test_name",
test_sauce: "test_sauce",
}).then((data) => {
console.log(data.toJSON());
}).catch((err) => {
console.log(err);
});
});
What the terminal displays when clicking submit:
{
id: 100,
test_name: 'test_name',
test_sauce: 'test_sauce',
updatedAt: 2022-12-21T02:54:42.447Z,
createdAt: 2022-12-21T02:54:42.447Z
}
I have tried to change and arrange both the HandleSubmit function as well as my app.post, but no matter what I do I cannot seem to get the form data from TestForm.js to index.js.
In your Server index.js you are not using the params you sent from the frontend.
It looks you are using express for you server.
Try doing something like
await TestTable.create({
test_name: req.body.test_name,
test_sauce: req.body.test_sauce
})
Check this: How to access the request body when POSTing using Node.js and Express?
I am working on an address book and I have fetched all the data from this API url:
https://jsonplaceholder.typicode.com/users
The API cannot really be modified, but it should behave "like if" according to this message in the documentation: "resource will not be really updated on the server but it will be faked as if."
I have set up the react hook form but when I submit my form this is what I get in the dev tools tab network? Shouldn't be showing the user inputs at this point instead of empty string for all fields? The id is the only thing that gets updated.
Is there anything wrong with my Submit function or the actual fetch? Is it ok I have the POST fetch in this component where I have my form as well or should be in the same component where I have the GET request?
Would this one be a good way to approach the POST request?
const NewUserForm = () => {
const { register, handleSubmit, formState: { errors } } = useForm();
const onSubmit = () => {
fetch(URL, {
method: 'POST',
body: JSON.stringify({
id:'',
name: '',
email: '',
address1:'',
address2:'',
city:'',
phone:''
}),
headers: {
'Content-type': 'application/json; charset=UTF-8'
},
})
.then((response) => response.json())
.then((json) => console.log(json));
}
return (
<>
<Header>New user</Header>
<FormContainer>
<Form onSubmit={handleSubmit(onSubmit)}>
<input type="text" placeholder="name" {...register("name", { required: true })} />
{errors.name && <span>This field is required</span>}
<input type="text" placeholder="email" {...register("email", { required: true })} />
{errors.email && <span>This field is required</span>}
<input type="text" placeholder="address1"{...register("address1", { required: true })} />
{errors.address1 && <span>This field is required</span>}
<input type="text" placeholder="address2"{...register("address2", { required: true })} />
{errors.address2 && <span>This field is required</span>}
<input type="text" placeholder="city"{...register("city", { required: true })} />
{errors.city && <span>This field is required</span>}
<input type="text" placeholder="phone"{...register("phone", { required: true })} />
{errors.phone && <span>This field is required</span>}
<input type="submit" />
</Form>
</FormContainer>
</>
);
}
Okay, after checking the react-hook-form docs, here is a possible solution:
In the docs, it says that your onSubmit will have a data param:
const onSubmit = (data) => alert(JSON.stringify(data));
Which means that you can use that in your onSubmit too.
Try changing your onSubmit to use the data parameter:
const onSubmit = (data) => {
fetch(URL, {
method: 'POST',
body: JSON.stringify(data),
And revert the change I suggested earlier regarding handleSubmit. This is correct:
<Form onSubmit={handleSubmit(onSubmit)}>
I'm currently working in react and have a couple of forms where the onSubmit functions automatically refresh the page even if I use preventDefault(). Im passing the event into the functions as well. Could really use some guidance on why these two forms are having this issue. It hasn't been a problem elsewhere.
Here's the form. Verify is automatically passing e.
<form onSubmit={verify} className='username-password-form'>
<div className='old-password-container'>
<label className='old-password-label'>Current Password:</label>
<input
className='old-password-input'
type='password'
id={`${id}-old-password`}
value={currentPassword}
name='currentPassword'
disabled={disabled}
onChange={(e) => setCurrentPassword(e.target.value)}
/>
<Button className='submit-old' type='submit'>
Submit
</Button>
</div>
</form>
Here's the verify function called onSubmit
const verify = async (e) => {
e.preventDefault();
const user = {
username: user_name,
password: currentPassword,
};
await fetch('http://localhost:3000/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(user),
});
setDisabled(true);
};
After i filled the inputs and submitted the form, I want to make a POST request with React. When i use fetch outside the handleSubmit function with a static name and job value, it works. But if i use inside the handleSubmit function, it doesn't work. Why? and how can i solve this?
import React from "react";
function CreateUser() {
const handleSubmit = (e) => {
e.preventDefault();
fetch("https://reqres.in/api/users", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({
name: `${e.target.name.value}`,
job: `${e.target.job.value}`,
}),
})
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log(err);
});
};
return (
<form onSubmit={handleSubmit}>
<label htmlFor="name">Name</label>
<input id="name" name="name" type="text" />
<label htmlFor="job">job</label>
<input id="job" name="job" type="text" />
<input type="submit" value="submit" />
</form>
);
}
export default CreateUser;
Can you check how to use fetch correctly. https://developers.google.com/web/ilt/pwa/working-with-the-fetch-api you need to return response.
Your react code seems fine, not sure how are you trying to handle success and error.
Check following Sandbox which I created using your code.
https://codesandbox.io/s/adoring-breeze-7fx2g?file=/src/App.js
In my react typescript app - I have a login component and a handleLoginRequest function which sets the userMessage value:
function Login() {
let [userMessage, setUserMessage] = useState("");
return (
<form className="form-inline" onSubmit={(e) => {
setUserMessage(handleLoginRequest(e))
}} >
<label className="mr-sm-2">Email address:</label>
<input type="email" className="form-control mb-2 mr-sm-2" placeholder="Enter email" id="email" />
<label className="mr-sm-2">Password:</label>
<input type="password" className="form-control mb-2 mr-sm-2" placeholder="Enter password" id="password" />
<button type="submit" className="btn btn-primary mb-2">Submit</button>
{userMessage}
</form>
);
}
Update: handleLoginRequest is a API request
const handleLoginRequest = (event: any): any => {
event.preventDefault();
const data = {
email: event.target.email.value,
password: event.target.password.value
};
axios.post(`${process.env.REACT_APP_HTTP_PROXY}/api/v1/login`, data)
.then(res => {
console.log(res.data);
return res.data;
})
.catch(err => {
console.log(err);
return err.message;
});
}
Expected behavior:
When the form is submitted, the function setUserMessage(handleLoginRequest(e)) is called. I expect that it update the value of userMessage to login request received.
Actual result:
No change in the value of userMessage
What is the fix here?
Updated answer per the question modification
The issue is stemming from the fact you're trying to setState based on a axios post request. Axios requests are asynchronous, meaning they will happen out of order with the program control flow. Therefore, to solve this issue, it is important you only make a call to setUserMessage when the request is complete.
Example Code:
axios.post(`${process.env.REACT_APP_HTTP_PROXY}/api/v1/login`, data)
.then(res => {
setUserMessage(res.data);
})
.catch(err => {
// Do Something with error response
setUserMessage("Error: Something with the request went wrong.");
});
I will link a codesandbox to demonstrate:
https://codesandbox.io/s/focused-leakey-0jer4