reactjs alert message and navigate - reactjs

I want that when i submit my form one i get a form submitted successfully message but when i submit my form it directly submits no message comes you have submitted your form successfully can someone tell me what to do or what i am doing wrong. and if possible on a side note can you tell me how to use the button to navigate to other page when i try that i am directly naviagted to home page.
Code :
const Account2 = () => {
const [menu, setMenu] = useState([])
const [form, setForm] = useState({
kookid: "",
kookname: "",
name: "",
cuisine: "",
foodtype: "",
spicylevel: "",
servings: "",
price: "",
description: "",
})
const menuCollectionRef = collection(db, "menu")
useEffect(() => {
onSnapshot(menuCollectionRef, snapshot => {
setMenu(snapshot.docs.map(doc => {
return {
id: doc.id,
viewing: false,
...doc.data()
}
}))
})
}, [])
const handleSubmit = e => {
e.preventDefault()
if (
!form.kookid ||
!form.kookname ||
!form.name ||
!form.cuisine ||
!form.foodtype ||
!form.spicylevel ||
!form.servings ||
!form.price ||
!form.description
) {
alert("Please fill out all fields")
return
alert("Form Submitted Successfully")
}
addDoc(menuCollectionRef, form)
setForm({
kookid: "",
kookname: "",
name: "",
cuisine: "",
foodtype: "",
spicylevel: "",
servings: "",
price: "",
description: "",
}).then(() => {
})
}
return (
<form onSubmit={handleSubmit}>
<div className="form-group2">
<label>Kook Id</label>
<input
type="text"
placeholder=""
value={form.kookid}
onChange={e => setForm({ ...form, kookid: e.target.value })} />
</div>
<div className="form-group2">
<label>Description</label>
<textarea
placeholder=""
value={form.description}
onChange={e => setForm({ ...form, description: e.target.value })} />
</div>
<center> <div className="buttons2">
<button type="submit">Submit</button>
</div></center>
</form>
</div></>

Related

"False" appearing in input after removing its text

After inserting text in input and later removing it completely with backspace "false" appears in it. It cannot be removed - after removing last letter it appears again. It appears in input which are rendered using map() method. The same problem doesn't occur in textarea which is not rendered using this method so I guess the problem lays somewhere here, but I dont have idea where.
export default function AddTodo({ active, setActive }: AddTodoProps) {
const { isDarkMode } = useContext(DarkModeContext);
const [todoDetails, setTodoDetails] = useState({
task: "",
description: "",
name: "",
deadline: "",
});
const { submitTodo, loading, status } = useAddTodoToDb(todoDetails);
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
setTodoDetails((prev) => {
return {
...prev,
[e.target.id]: e.target.value || e.target.checked,
};
});
};
useEffect(() => {
if (typeof status == "string")
setTodoDetails({
task: "",
description: "",
name: "",
deadline: "",
});
}, [status]);
return (
{todoInputs.map((item) => {
return (
<StyledLabelAndInput
isDarkMode={isDarkMode}
err={status?.includes(item.id)}
key={item.id}
>
<label htmlFor={item.id}>{item.text}</label>
<input
value={todoDetails[item.id as keyof ITodoDetails]}
type={item.type}
id={item.id}
min={today}
onChange={(e) => handleChange(e)}
/>
</StyledLabelAndInput>
);
})}
<label htmlFor="description">Description (optional)</label>
<textarea
value={todoDetails.description}
id="description"
onChange={(e) =>
setTodoDetails((prev) => {
return {
...prev,
description: e.target.value,
};
})
}
/>
The false value is comming from the input's checked attribute.
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
setTodoDetails((prev) => {
return {
...prev,
[e.target.id]: e.target.value || e.target.checked, /* <--- HERE */
};
});
};
You're trying to get the input's value OR checked, and since the input has no value it's returning the checked attribute, which is false by default.
Instead you'll need to check if the item type is checkbox before using the checked attribute.

Updating a form object with React useReducer

I have a controlled form containing an address object.
const [formData, setFormData] = useReducer(formReducer, {
name: "",
address: { addressLine1: "", city: "", state: "", zip: "" },
phone: "",
contact: "",
});
const formReducer = (state, event) => {
return {
...state,
[event.name]: event.value,
};
};
Updating a form input triggers a handler function.
<input
className={style.bodylessInput}
placeholder=" "
type="text"
maxLength={30}
name="name"
value={formData.name}
onChange={handleChange}
/>
function handleChange(event) {
setFormData({
name: event.target.name,
value: event.target.value,
});
}
I am struggling to update the address fields. Using an input with name="addressLine1" will add a property to the form object rather than update the address.
Any advice on how I can update the address object inside my form object would be appreciated.
You can do as below. input name be like address.addressLine1
function formReducer(state, event) {
if(event.name.startsWith("address") && event.name.split(".").length > 1){
var updateField = event.name.split(".")[1];
return{
...state,
address:
{...state.address, [updateField] : event.value}
}
}
return {
...state,
[event.name]: event.value,
};
}
input:
<input
type="text"
maxLength={30}
name="address.addressLine1"
value={formData.address.addressLine1}
onChange={handleChange}
/>

How can i set value in nested object in React?

how can I set value from text Input to option[0].title when user input? I tried in many way and get error. Please help me to fix this issue.
const [options, setOptions] = useState({
0: {
title: "",
},
2: {
title: "",
1: {
title: "",
}, },
3: {
title: "",
},
title: "", });
let name, value;
const handleChange = (e) => {
name = e.target.name;
value = e.target.value;
setOptions({ ...options, [name]: value }); };
return ( <TextInput
type="text"
name="0"
value={options[0].title}
onChange={handleChange}
required
placeholder="something"
icon="check_box_outline_blank"
/> )
you just have to edit the title in the object:
const handleChange = (e) => {
name = e.target.name;
value = e.target.value;
setOptions({ ...options, [name]: { title: value } });
};
and if you need the previous information from the targeted name, spread within that object too:
setOptions({ ...options, [name]: { ...options[name], title: value } });
Fully working code,
const [options, setOptions] = useState({
0: { title: "" },
2: {
title: "",
1: { title: "" },
},
3: { title: "" },
title: "",
});
const handleChange = (e) => {
const { name, value } = e.target;
options[+name].title = value;
setOptions({...options});
};
return (
<>
<input
type="text"
name="0"
value={options[0].title}
onChange={handleChange}
required
placeholder="something"
icon="check_box_outline_blank"
/>
<input
type="text"
name="2"
value={options[2].title}
onChange={handleChange}
required
placeholder="something"
icon="check_box_outline_blank"
/>
</>
);
I tried to check this on codesandbox and found a solution -
The name that you have updated here is string and the json has number keys. Which was the reason why it wouldn't update on title node. Also you never said .title = value, which is why values got directly updated to the options[0] element
export default function App() {
const [options, setOptions] = useState({
0: {
title: ""
},
2: {
title: "",
1: {
title: ""
}
},
3: {
title: ""
},
title: ""
});
const handleChange = (e) => {
const name = e.target.name,
value = e.target.value;
let updatedOptions = { ...options };
updatedOptions[Number(name)].title = value;
setOptions(updatedOptions);
};
return (
<div className="App">
<input
type="text"
name="0"
value={options[0].title}
onChange={handleChange}
required
placeholder="something"
icon="check_box_outline_blank"
/>
</div>
);
}

React: Nested Array Form - Input field onChange handler

The form data is set by an the data object. Need help figuring out how to update /handleChange the text inputs
I've tried unique name, those probably won't work because it wont match the "key" in the object.
Any help / input is appreciated!
Data:
export default
{
name: "Restaurants Name",
menu: [
{
category: "Appetizers",
items:
[ {
imgurl: "https://source.unsplash.com/400x200/?863127",
title: "Food 2",
desc: "",
price: "500"
},
{
imgurl: "",
title: "Food 1",
desc: "",
price: "300"
}
]
},
{
category: "Entree",
items:
[ {
imgurl: "https://source.unsplash.com/400x200/?863127",
title: "Entree 1",
desc: "",
price: "500"
},
{
imgurl: "",
title: "Entree 1",
desc: "",
price: "300"
}
]
},
]
}
Code:
import React, { useEffect, useState } from "react";
import "./../App.css"
import MenuData from "../data"
function Edit() {
const [formState, setFormState] = useState(MenuData);
useEffect(() => {
console.log(formState)
}, []);
const handleNameChange = (event) => {
const name = event.target.name;
// console.log(name)
setFormState(prevState => ({
formState: { // object that we want to update
...prevState.formState, // keep all other key-value pairs
[name]: event.target.value, // update the value of specific key
menu: {
...prevState.menu,
items: {
...prevState.menu.items
}
}
}
}))
// setFormState({
// ...formState,
// [name]: event.target.value,
// })
};
const handleChange = (categoryIndex, event) => {
// const values = [...formState]
// values[categoryIndex][event.target.name] = event.target.value;
// setFormState(values);
const name = event.target.name;
// setFormState(prevState => ({
// formState: {
// ...prevState.formState,
// menu: {
// ...prevState.menu,
// items{
// ...prevState.items
// }
// }
// }
// }));
};
return (
<div className="App">
<div>
<input name="nameField" id="nameField" maxLength="300" value={formState.name} onChange={handleNameChange} /> <br />
{formState.menu && formState.menu.map((menuitem, categoryIndex) => {
return (
<div key={categoryIndex}>
<div class="line"></div>
<h2>{menuitem.category}</h2>
<input name={"category-" + categoryIndex} id="CategoryField" maxLength="40" categoryIndex={categoryIndex} onChange={event => handleChange(categoryIndex, event)} value={menuitem.category} />
{
menuitem.items.map((item, index) => {
return(
<div key={index}>
<input name={"title-" + index + categoryIndex} id="titleField" maxLength="40" categoryIndex={categoryIndex} onChange={handleChange} value={item.title} /> <br />
<input name="desc" id="descField" maxLength="200" categoryIndex={categoryIndex} onChange={handleChange} value={item.desc} />
<br /><br />
</div>
)
})
}
</div>
)
}
)
}
</div>
</div>
);
}
export default Edit;
UPDATED
Not able to figure out the onChange function to updated nested items

Save data to firebase

enter image description here
I am building this meeting booking app where the available meetings to books shows as buttons and after klicking the meeting you want so select. I want to make it possible to save that information in the button with a name and email that is written in the form.
I am having it hard to set the code so that my button selection is saved and saved to firebase along with the name and email after submit button is pressed. Right know I get the error that 'set' in handleSubmit is not set.
import React, { Component } from "react";
import "./App.css";
import firebase from "firebase";
const uuid = require("uuid");
class App extends Component {
constructor(props) {
super(props);
this.state = {
uid: uuid.v1(),
meeting: "",
name: "",
email: ""
};
this.handleClick = this.handleClick.bind(this);
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
var config = {
apiKey: "",
authDomain: "",
databaseURL: "",
projectId: "",
storageBucket: "",
messagingSenderId: ""
};
firebase.initializeApp(config);
// console.log(firebase);
var database = firebase.database();
var ref = database.ref("meeting");
var data = {
id: "",
user: ""
};
ref.push(data);
// this.state = {
// items: [],
// isLoaded: true,
// }
// this.state = {
// name: '',
// email: '',
// };
}
handleClick = e => {
console.log(e.target.innerHTML);
alert("Du har valt ett möte");
};
componentDidMount() {
fetch("http://www.mocky.io/v2/5c9cdca03300004d003f2151")
.then(res => res.json())
.then(json => {
let meetings = [];
json.forEach(meeting => {
if (
new Date(meeting.startDate).getDay() !==
new Date(meeting.endDate).getDay()
) {
let day1 = {
activity: meeting.activity,
location: meeting.location,
startDate: meeting.startDate
};
let day2 = {
activity: meeting.activity,
location: meeting.location,
endDate: meeting.endDate
};
meetings.push(day1, day2);
} else {
meetings.push(meeting);
}
});
console.log(meetings);
this.setState({
isLoaded: true,
items: meetings
});
});
firebase
.database()
.ref(`Newdata/${this.state.uid}`)
.on("value", snap => console.log("from db", snap.val()));
}
handleChange(e) {
this.setState({
name: e.target.name
});
}
handleSubmit(e) {
alert("Er bokning är bekräftad: " + this.state.value);
console.log("Du har bekräftat er bokning");
e.preventDefault();
firebase.database().ref(`Newdata/${this.state.uid}`);
set({
meeting: this.state.meeting,
name: this.state.name,
email: this.state.email
}).catch(error => console.log(error));
}
inputData(e) {
const meeting = this.refs.meeting1.value;
const name = this.refs.name1.value;
const email = this.refs.email1.value;
this.setState({ meeting, name, email });
}
render() {
var { isLoaded, items } = this.state;
if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<>
<div className="App">
<div className="AppHeader">
<h1>Boka ditt möte nedan</h1>
</div>
<ul>
{items.map((item, i) => (
<li key={i}>
<button
onClick={e => this.handleClick(e)}
onChange={this.inputData}
className="select"
>
{item.activity}
<br />
Starttid: {item.startDate}
<br />
Sluttid: {item.endDate}
<br />
Plats: {item.location}
<br />
</button>
</li>
))}
</ul>
</div>
<div className="selectedMeeting">
Fyll i dina uppgifter och bekräfta
</div>
<form onSubmit={this.handleSubmit} className="bookingSection">
<label>
Name:
<input
type="text"
name={this.state.name}
onChange={this.inputData}
onChange={this.handleChange}
ref="name1"
/>
</label>
<label>
E-mail:
<input
type="text"
email={this.state.email}
onChange={this.inputData}
onChange={this.handleChange}
ref="email1"
/>
</label>
<input className="confirm" type="submit" value="Bekräfta" />
</form>
<div className="viewSelect" />
</>
);
}
}
}
export default App;
TL;DR;
You have a typo in your code, it should be:
firebase.database().ref('Newdata/${this.state.uid}').set({
meeting: this.state.meeting,
name: this.state.name,
email: this.state.email
}).catch(error => console.log(error));
Explanation:
Since you add the ;, you end the first expression and start a new one that is:
set({
meeting: this.state.meeting,
name: this.state.name,
email: this.state.email
}).catch(error => console.log(error));
Since there is no function defined, Javascript gives this error. But what you want do do is call the method set of the object firebase.database().ref('Newdata/${this.state.uid}'), therefore you should do:
firebase.database().ref('Newdata/${this.state.uid}').set({ /* ... */ })

Resources