I'm trying to post multiple variables to my Postgres database using a form with React.
This is my current script:
const InputAddress = () => {
const [name, setName] = useState("");
const [problem, setProblem] = useState("");
const [date, setDate] = useState("");
const onSubmitForm = async (e) => {
e.preventDefault();
try {
const body = {
name,
problem,
date,
};
console.log(params);
const response = await fetch("http://localhost:5000/logements", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
});
console.log(response);
window.location = "/";
} catch (error) {
console.log(error.message);
}
};
return (
<Fragment>
<h1 className="text-center mt-5">Add your address</h1>
<form className="d-flex mt-5" onSubmit={onSubmitForm}>
<label>Name</label>
<input
type="text"
className="form-control"
value={name}
onChange={(e) => setName(e.target.value)}
/>
<label>Comment</label>
<input
type="text"
className="form-control"
value={problem}
onChange={(e) => setProblem(e.target.value)}
/>
<label>Date</label>
<input
type="text"
className="form-control"
value={date}
onChange={(e) => setDate(e.target.value)}
/>
<button className="btn btn-success">Submit</button>
</form>
</Fragment>
);
};
My problem seems to be with the fetch method.
When I submit the form, I get this error message in the console :
bind message supplies 1 parameters, but prepared statement "" requires 3
Is there a simple fix to this problem?
Related
I am learning React from few days and I am trying to learn Axios, Everything worked fine until I tried to insert data, which I successfully inserted but My React Page did not updated contact list immediately.
HERE's MY CODE:
App.js
import Axios from "axios";
import React, { useEffect, useState } from "react";
import Add__Contact from "./api/Add__Contact";
const App = () => {
const [name, setName] = useState("");
const [phone, setPhone] = useState("");
const [contacts, setContacts] = useState([]);
const url = "http://localhost:3006/contacts";
//get all availbale contacts
useEffect(() => {
// get all contacts async
async function getUsers() {
Axios.get(url).then((response) => {
setContacts(response.data);
});
}
getUsers();
console.log(contacts);
// get all contacts non-async
// Axios.get(url).then((response) => {
// setContacts(response.data);
// });
}, []);
//add new contact to server
const addContact = () => {
const saveRes = Add__Contact({ name, phone });
};
// view
return (
<div>
<h4>Add contact</h4>
<div>
<input type="text" name="name" value={name} onChange={(e) => setName(e.target.value)} placeholder="name here" />
<br />
<br />
<input
type="text"
name="phone"
value={phone}
onChange={(e) => setPhone(e.target.value)}
placeholder="Phone here"
/>
<br />
<br />
<button onClick={addContact}>Add to Contact</button>
</div>
<hr />
<h4>List of Contacts</h4>
<div>
{contacts.map((contact) => {
return (
<div key={contact.id}>
<span>{contact.name} : </span>
<span> {contact.phone}</span>
</div>
);
})}
</div>
</div>
);
};
export default App;
Add__Contact.js
import Axios from "axios";
const Add__Contact = async ({ name, phone }) => {
Axios({
method: "post",
url: "http://localhost:3006/contacts",
headers: {
"Content-Type": "application/json",
},
data: {
name,
phone,
},
}).then(function (res) {
// console.log(res);
});
};
export default Add__Contact;
db.json
{
"contacts": [
{
"name": "Max",
"phone": "123456",
"id": 1
},
{
"name": "John",
"phone": "13454",
"id": 2
},
{
"name": "Candy",
"phone": "1245781245",
"id": 3
}
]
}
I am not sure why it's not updating list automatically, I thought useEffect will run everytime I click and call Add__Contact(). Can you please tell me what did i missed or doing wrong?
I am not sure if useEffect hook is good for what I want to achieve or not, so please guide me. Thank you in advance.
data insertion is working fine, but after I insert it, it's not updating ui, even if I am fetching data inside useEffect
Your useEffect hook is only ran once - when the component mounts. This is because you have given it an empty dependency array (the 2nd argument).
The dependency array determines when the effect function will run. If its empty, it will only run when the component is mounted (displayed for the very first time). If you add something in the array, the effect will run on mount, and whenever the provided value changes.
In your case, you have an event (the click event from the Add to Contacts button) after which you want your data to be fetched again. But you also want to fetch data when the page loads.
One way to do it is something like this:
const Add__Contact = async ({ name, phone }) => {
// Return the Promise returned from the Axios call
return Axios({
method: "post",
url: "http://localhost:3006/contacts",
headers: {
"Content-Type": "application/json",
},
data: {
name,
phone,
},
});
};
const App = () => {
const [name, setName] = useState("");
const [phone, setPhone] = useState("");
const [contacts, setContacts] = useState([]);
const url = "http://localhost:3006/contacts";
// Add a function to fetch contacts
const fetchContacts = async () => {
const res = await Axios.get(url);
setContacts(res.data);
};
// Effect that fetches contacts when the component loads
useEffect(() => {
fetchContacts();
}, []);
//add new contact to server
const addContact = async () => {
// await the Promise returned
const saveRes = await Add__Contact({ name, phone });
// Fetch the contacts list again
await fetchContacts();
};
// view
return (
<div>
<h4>Add contact</h4>
<div>
<input type="text" name="name" value={name} onChange={(e) => setName(e.target.value)} placeholder="name here" />
<br />
<br />
<input
type="text"
name="phone"
value={phone}
onChange={(e) => setPhone(e.target.value)}
placeholder="Phone here"
/>
<br />
<br />
<button onClick={addContact}>Add to Contact</button>
</div>
<hr />
<h4>List of Contacts</h4>
<div>
{contacts.map((contact) => {
return (
<div key={contact.id}>
<span>{contact.name} : </span>
<span> {contact.phone}</span>
</div>
);
})}
</div>
</div>
);
};
So you'r Contacts Array is not updated .Even you got a data from axios call .
Like if axios is returning data then i think you'r state in not updating then you have to use
setContacts((prv)=>[...prv,...res.data])
If you'r facing problem on Add time . Then make a separate function then use that in useEffect() && your ADD_Contact() .
const App = () => {
const [name, setName] = useState("");
const [phone, setPhone] = useState("");
const [contacts, setContacts] = useState([]);
const getContacts = async () => {
const res = await Axios.get('http://localhost:3006/contacts');
setContacts(res.data);
};
useEffect(() => {
getContacts();
}, []);
const addContact = async () => {
const saveRes = await Add__Contact({ name, phone });
await getContacts();
};
return (
<div>
<h4>Add contact</h4>
<div>
<input type="text" name="name" value={name} onChange={(e) => setName(e.target.value)} placeholder="name here" />
<br />
<br />
<input
type="text"
name="phone"
value={phone}
onChange={(e) => setPhone(e.target.value)}
placeholder="Phone here"
/>
<br />
<br />
<button onClick={addContact}>Add to Contact</button>
</div>
<hr />
<h4>List of Contacts</h4>
<div>
{contacts.map((contact) => {
return (
<div key={contact.id}>
<span>{contact.name} : </span>
<span> {contact.phone}</span>
</div>
);
})}
</div>
</div>
);
};
I have a contact form, when the form submission is successful it should clear the form field name, email and message which is tied up to the state. The form submission is successful but form fields name, email and message doesn't clear.
For test purpose what I'm doing is passing default values to the state but this values doesn't get filled in form during initial load.
export default function Contact() {
const [name, setName] = useState('John Doe')
const [email, setEmail] = useState('me#example.com')
const [message, setMessage] = useState('Hello, this is test message.')
const onSubmit = (e) => {
e.preventDefault()
const form = {"name": name, "email": email, "message": message}
return fetch('/api/contact', {
method: 'POST',
body: JSON.stringify(form),
headers: {'Content-Type': 'application/json'}
}).then(response => {
if(response.status === 200){
setName('')
setEmail('')
setMessage('')
} else {
}
}).catch(err => err)
}
return (
<section>
<form method='post'>
<div>
<label>Name</label>
<input type="text" name="name" onChange={(e) => {setName(e.target.value)}}/>
</div>
<div>
<label>Email Address</label>
<input type="email" name="email" onChange={(e) => {setEmail(e.target.value)}}/>
</div>
<div>
<label>Message</label>
<textarea minLength={5} maxLength={2000} rows="6" name="message" onChange={(e) => {setMessage(e.target.value)}}></textarea>
</div>
<div>
<button type='submit' onClick={(e) => {onSubmit(e)}}>Send Message</button>
</div>
</form>
</section>
);
}
As User456 said, you need to add value={variable} for every <input />.
Example:
import { useState } from "react";
export default function Contact() {
const [name, setName] = useState("John Doe");
const [email, setEmail] = useState("me#example.com");
const [message, setMessage] = useState("Hello, this is test message.");
const onSubmit = (e: any) => {
e.preventDefault();
setName("");
setEmail("");
setMessage("");
};
return (
<section>
<form method="post">
<div>
<label>Name</label>
<input
type="text"
name="name"
value={name}
onChange={e => {
setName(e.target.value);
}}
/>
</div>
<div>
<label>Email Address</label>
<input
type="email"
name="email"
value={email}
onChange={e => {
setEmail(e.target.value);
}}
/>
</div>
<div>
<label>Message</label>
<textarea
minLength={5}
maxLength={2000}
name="message"
value={message}
onChange={e => {
setMessage(e.target.value);
}}></textarea>
</div>
<div>
<button
type="submit"
onClick={e => {
onSubmit(e);
}}>
Send Message
</button>
</div>
</form>
</section>
);
}
I have an issue when i am trying to post to my API (Net6.0) because i get the error of 400 fetch, i have tried different things that i have found on here but i cant seem to fix it.
Here is my code:
my function:
const [title, setTitle] = useState('');
const [description, setDescription] = useState('');
const [link, setLink] = useState('');
const handleSubmit =(e) => {
e.preventDefault();
const post = { title, description, link };
fetch('https://localhost:7018/api/Posts', {
method: 'POST',
headers: { "Content-Type": "application/json" },
body: JSON.stringify(post)
}).then(() => {
console.log('new post added');
// GoBack()
})
}
and my return:
<div className="create">
<form onSubmit={handleSubmit}>
<label>Titel</label>
<input
type="text"
required
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
<label>Description</label>
<textarea
required
value={description}
onChange={(e) => setDescription(e.target.value)}
></textarea>
<label>Link</label>
<input
type="text"
required
value={link}
onChange={(e) => setLink(e.target.value)}
/>
<button>Skapa Inlägg</button>
<p>{ title }</p>
<p>{ description }</p>
<p>{ link }</p>
</form>
</div>
here is the error code i get
[1]: https://i.stack.imgur.com/WHwTn.png
I have a React app in front-end with ASP.NET Web Api in back-end. When I try to make a PUT request from React to Web Api in the console appears error with number 400. With all other requests everything is fine. I put a breakpoint in ASP.NET in debug but even then request doesn't get in Web API.
This is my code in React:
import React, { useState, useEffect, useCallback } from 'react';
import { useNavigate } from 'react-router-dom';
import styles from './editContact.module.css';
const EditContact = () => {
const id = window.location.pathname.slice(14);
const navigate = useNavigate();
const [contactName, setContactName] = useState('');
const [email, setEmail] = useState('');
const [phone, setPhone] = useState('');
const [description, setDescription] = useState('');
const [categories, setCategories] = useState('');
const [areas, setAreas] = useState('');
const [event, setEvent] = useState('');
const [continent, setContinent] = useState('');
const [country, setCountry] = useState('');
const getContact = useCallback (async () => {
const request = await fetch(`https://localhost:7082/api/contacts/${id}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
});
const response = await request.json();
setContactName(response.name);
setEmail(response.email);
setAreas(response.areas);
setCategories(response.categories);
setDescription(response.description);
setEvent(response.event);
setPhone(response.phoneNumber);
setContinent(response.continent);
setCountry(response.country);
}, [id]);
const sendToHome = () => {
navigate('/');
};
const editContact = async (e) => {
e.preventDefault();
await fetch(`https://localhost:7082/api/contacts/${id}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
contactName,
email,
phone,
description,
areas,
event,
categories,
continent,
country
})
})
.then(() => {
navigate('/');
})
.catch((e) => {
alert(e.message);
})
};
useEffect(() => {
getContact();
}, [getContact]);
return (
<form className={styles.form} onSubmit={editContact}>
<div className="form-group">
<label htmlFor="exampleFormControlInput1">Name</label>
<input type="text" className="form-control" id="exampleFormControlInput1" onChange={e => setContactName(e.target.value)} value={contactName} />
</div>
<div className="form-group">
<label htmlFor="exampleFormControlInput1">eMail</label>
<input type="email" className="form-control" id="exampleFormControlInput1" onChange={e => setEmail(e.target.value)} value={email} />
</div>
<div className="form-group">
<label htmlFor="exampleFormControlInput1">Phone</label>
<input type="text" className="form-control" id="exampleFormControlInput1" onChange={e => setPhone(e.target.value)} value={phone} />
</div>
<div className="form-group">
<label htmlFor="exampleFormControlInput1">Description</label>
<input type="text" className="form-control" id="exampleFormControlInput1" onChange={e => setDescription(e.target.value)} value={description} />
</div>
<div className="form-group">
<label htmlFor="exampleFormControlInput1">Categories</label>
<input type="text" className="form-control" id="exampleFormControlInput1" onChange={e => setCategories(e.target.value)} value={categories} />
</div>
<div className="form-group">
<label htmlFor="exampleFormControlInput1">Areas</label>
<input type="text" className="form-control" id="exampleFormControlInput1" onChange={e => setAreas(e.target.value)} value={areas} />
</div>
<div className="form-group">
<label htmlFor="exampleFormControlInput1">Event</label>
<input type="text" className="form-control" id="exampleFormControlInput1" onChange={e => setEvent(e.target.value)} value={event} />
</div>
<button type='submit' className='btn btn-success mt-5' style={{ marginRight: 5 + 'px' }} name='edit'>Submit</button>
<button className='btn btn-secondary mt-5' onClick={sendToHome}>Cancel</button>
</form>
);
};
export default EditContact;
And this is my code in ASP.NET:
[Route("api/[controller]")]
[ApiController]
public class ContactsController : ControllerBase
{
private readonly IContactsService contactsService;
public ContactsController(IContactsService contactsService)
{
this.contactsService = contactsService;
}
[HttpGet]
public JsonResult AllContacts()
{
var result = this.contactsService.GetAllContacts();
return new JsonResult(result);
}
[HttpGet("{id}")]
public JsonResult ContactDetails(string id)
{
var result = this.contactsService.GetContactDetails(id);
return new JsonResult(result);
}
[HttpPost]
public ActionResult AddContact(AddContactViewModel model)
{
if (!this.ModelState.IsValid)
{
return this.BadRequest();
}
this.contactsService.AddContact(model);
return this.Ok();
}
[HttpPut("{id}")]
public ActionResult EditContact(string id, EditContactViewModel model)
{
this.contactsService.EditContact(id, model);
return this.Ok();
}
}
I will happy if someone could help me.
I have a problem with my code. I have a tag with options, when I try to set contact type set contact type appears white screen with error in the console "types.map() is not a function" white screen with errors. I think the problem comes from that at the beginning "types" are array and when I choose contact type with the state() "types" become a single value. I don't know how to fix that.
This is my code:
import React, { useState, useEffect } from "react";
import { useNavigate } from "react-router-dom";
import styles from './postContact.module.css';
const PostContact = () => {
const [nickName, setNickName] = useState('');
const [address, setAddress] = useState('');
const [phoneNumber, setPhoneNumber] = useState('');
const [account, setAccount] = useState('');
const [types, setType] = useState([]);
const navigate = useNavigate();
const postContact = async (e) => {
e.preventDefault();
await fetch('http://localhost:5090/api/contacts', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
nickName,
address,
phoneNumber,
userId: 1,
contactTypeId: types,
account
})
})
.then(() => {
navigate('/');
})
.catch((e) => {
alert(e.message)
});
};
const getTypes = async () => {
const request = await fetch('http://localhost:5090/api/contactTypes', {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
});
const response = await request.json();
setType(response);
};
useEffect(() => {
getTypes();
}, []);
return (
<form className={styles['post-form']} onSubmit={postContact}>
<label htmlFor='nickName'>Nickname</label>
<input className={styles.input} id='nickName' type='text' onChange={e => setNickName(e.target.value)} value={nickName} />
<label htmlFor='address'>Address</label>
<textarea className={styles.input} id='address' type='text' onChange={e => setAddress(e.target.value)} value={address} />
<label htmlFor='phoneNumber'>Phone Number</label>
<input className={styles.input} id='phoneNumber' type='text' onChange={e => setPhoneNumber(e.target.value)} value={phoneNumber} />
<label htmlFor='account'>Account</label>
<input className={styles.input} id='account' type='text' onChange={e => setAccount(e.target.value)} value={account} />
<label htmlFor="type">Contact Type</label>
<select className={styles.input} title="type" name="type" onChange={e => setType(e.target.value)} value={types}>
{types.map(type=>
<option key={type.id} value={type.id}>{type.type}</option>
)}
</select>
<button className="btn btn-primary mt-5" type='submit' name='Post'>Create</button>
</form>
);
};
export default PostContact;
I'll be grateful if anyone can help me.
On the first render the value for types will be undefined ( on sync code execution ), try using it as
<select className={styles.input} title="type" name="type" onChange={e => setType(e.target.value)} value={types}>
{types?.map(type=>
<option key={type.id} value={type.id}>{type.type}</option>
)}
</select>
? will make sure to run map once value for types is there ( also make sure it is mappable ( is an array ))
Handle the array falsy cases before doing any operations on it
<select
className={styles.input}
title="type" name="type"
onChange={e => setType(e.target.value)}
value={types}
>
{types.length && types.map(type=>
<option key={type.id} value={type.id}>{type.type}</option>
)}
</select>