After editing only one field is edited and the other one behaves unexpectedly (React hooks) - javascript

I have very simple ediable book-list. But when I press 'edit' and edit just one of two fields the other one behaves unexpectedly (it clears out even tho there was a value, or takes unexpected value from God knows where). It works correctly only if I edit both fields at once.
Here's my code:
import './App.css';
import React, { useState, useEffect } from 'react';
function App() {
const [books, setBooks] = useState([]);
const [book, setBook] = useState({
id: '',
title: '',
author: ''
});
const [alertMessage, setAlertMessage] = useState(false);
const [successMessage, setSuccessMessage] = useState(false);
const [editMode, setEditMode] = useState(null);
const [titleValue, setTitleValue] = useState('');
const [authorValue, setAuthorValue] = useState('');
useEffect(()=> {
const data = localStorage.getItem('books');
if(data) {
setBooks(JSON.parse(data))
}
}, [])
useEffect(()=> {
localStorage.setItem('books', JSON.stringify(books))
},)
function addBook (e) {
e.preventDefault();
if(!book.title && !book.author){
setAlertMessage(true)
setTimeout(()=>setAlertMessage(false), 3000)
} else {
let newBook = {
...book,
id: Math.floor(Math.random() * 100000000),
};
setBooks([newBook, ...books]);
setBook({
title: '',
author: ''
});
setSuccessMessage(true)
setTimeout(()=>setSuccessMessage(false), 1000);
}
}
function deleteBook(id){
setBooks(books.filter(book => book.id !== id))
}
function editBook(id) {
setEditMode(id);
}
function onChange(e) {
setBook({
...book,
[e.target.name]: e.target.value
})
}
function saveChanges (id) {
let newBook = [...books].map(book => {
if(book.id === id) {
book.title = titleValue;
book.author = authorValue
}
return book
});
setBook(newBook);
setEditMode(null)
}
return (
<div className='container'>
{alertMessage && <div className='alertMeaage'>Please, enter book author or its title</div>}
{successMessage && <div className='successMessage'>Book is successfully added!</div>}
<div className='BookForm'>
<h3>Add book</h3>
<input name='title' type='text' placeholder='Enter book title' value={book.title} onChange={onChange}/>
<input name='author' type='text' placeholder='Enter book author' value={book.author} onChange={onChange}/>
<button className='submitBtn' onClick={addBook}>Send</button>
</div>
<div>
<h4>Recently added books:</h4>
<div key={book.id}>{books.map(book => (
<div className='bookItem'>
{editMode !== book.id ? <><span className='titleAuthor'>Title: </span><i>«{book.title}» </i>
<span className='titleAuthor'>Author: </span> <i>{book.author}</i>
<button onClick={()=>deleteBook(book.id)} className='deleteBtn'>X</button>
<button onClick={()=>editBook(book.id)} className='editBtn'>Edit</button></>
:
<form className='form'>
<input name='title' type='text' defaultValue={book.title} onChange={(e)=> setTitleValue(e.target.value)}/>
<input name='author' type='text' defaultValue={book.author} onChange={(e)=> setAuthorValue(e.target.value)}/>
<button className='saveBtn' onClick={()=>saveChanges(book.id)}>Save</button>
</form>
}
</div>
))}
</div>
</div>
</div>
);
}
export default App;
Thanks a lot in advance!

When you edit new book, authorValue and titleValue still have previous values, so you must setAuthorValue and setTitleValue in editBook function. See below:
function editBook(book) {
setEditMode(book.id);
setTitleValue(book.title);
setAuthorValue(book.author);
}
And handle event:
<button onClick={() => editBook(book)} className="editBtn">
Edit
</button>
All code:
// import './App.css';
import React, { useState, useEffect } from "react";
function App() {
const [books, setBooks] = useState([]);
const [book, setBook] = useState({
id: "",
title: "",
author: ""
});
const [alertMessage, setAlertMessage] = useState(false);
const [successMessage, setSuccessMessage] = useState(false);
const [editMode, setEditMode] = useState(null);
const [titleValue, setTitleValue] = useState("");
const [authorValue, setAuthorValue] = useState("");
useEffect(() => {
const data = localStorage.getItem("books");
if (data) {
setBooks(JSON.parse(data));
}
}, []);
useEffect(() => {
localStorage.setItem("books", JSON.stringify(books));
});
function addBook(e) {
e.preventDefault();
if (!book.title && !book.author) {
setAlertMessage(true);
setTimeout(() => setAlertMessage(false), 3000);
} else {
let newBook = {
...book,
id: Math.floor(Math.random() * 100000000)
};
setBooks([newBook, ...books]);
setBook({
title: "",
author: ""
});
setSuccessMessage(true);
setTimeout(() => setSuccessMessage(false), 1000);
}
}
function deleteBook(id) {
setBooks(books.filter((book) => book.id !== id));
}
function editBook(book) {
setEditMode(book.id);
setTitleValue(book.title);
setAuthorValue(book.author);
}
function onChange(e) {
console.log(e.target.name, e.target.value);
setBook({
...book,
[e.target.name]: e.target.value
});
}
function saveChanges(id) {
let newBook = [...books].map((book) => {
if (book.id === id) {
book.title = titleValue;
book.author = authorValue;
}
return book;
});
setBook(newBook);
setEditMode(null);
}
return (
<div className="container">
{alertMessage && (
<div className="alertMeaage">
Please, enter book author or its title
</div>
)}
{successMessage && (
<div className="successMessage">Book is successfully added!</div>
)}
<div className="BookForm">
<h3>Add book</h3>
<input
name="title"
type="text"
placeholder="Enter book title"
value={book.title}
onChange={onChange}
/>
<input
name="author"
type="text"
placeholder="Enter book author"
value={book.author}
onChange={onChange}
/>
<button className="submitBtn" onClick={addBook}>
Send
</button>
</div>
<div>
<h4>Recently added books:</h4>
<div key={book.id}>
{books.map((book) => (
<div className="bookItem">
{editMode !== book.id ? (
<>
<span className="titleAuthor">Title: </span>
<i>«{book.title}» </i>
<span className="titleAuthor">Author: </span>{" "}
<i>{book.author}</i>
<button
onClick={() => deleteBook(book.id)}
className="deleteBtn"
>
X
</button>
<button onClick={() => editBook(book)} className="editBtn">
Edit
</button>
</>
) : (
<form className="form">
<input
name="title"
type="text"
defaultValue={book.title}
onChange={(e) => setTitleValue(e.target.value)}
/>
<input
name="author"
type="text"
defaultValue={book.author}
onChange={(e) => setAuthorValue(e.target.value)}
/>
<button
className="saveBtn"
onClick={() => saveChanges(book.id)}
>
Save
</button>
</form>
)}
</div>
))}
</div>
</div>
</div>
);
}
export default App;

Related

Does not see the function when outputting reactjs

On the main page without a Header, this function works. I want to make it on a separate page, it doesn't work.
I looked at examples, everything converges, does not display on a separate page.
Аrom addpeople to add, header(example <\h1>text<\h1> or other works.
\addpeople.js
import React, { Component } from 'react';
import "./add.css";
import { useState } from "react";
import Axios from "axios";
import { Button } from "react-bootstrap";
import 'bootstrap/dist/css/bootstrap.min.css';
function newcreate() {
return (
function App() {
const [surename_ru, setSurename_ru] = useState("");
const [name_ru, setName_ru] = useState(0);
const [fname_ru, setFname_ru] = useState("");
const [surename_en, setSurename_en] = useState("");
const [name_en, setName_en] = useState(0);
const [gender, setGender] = useState("");
const [dateofbirth, setDateofbirth] = useState(0);
const [citizenship, setCitizenship] = useState("");
const [pas_ser, setPas_ser] = useState("");
const [pas_num, setPas_num] = useState(0);
const [pas_start, setPas_start] = useState("");
const [pas_end, setPas_end] = useState(0);
const [pas_given, setPas_given] = useState("");
const [pas_givenkod, setPas_givenkod] = useState("");
const [inn_num, setInn_num] = useState(0);
const [snils_num, setSnils_num] = useState("");
const [legal_type, setLegal_type] = useState(0);
const [newWage, setNewWage] = useState(0);
const [employeeList, setEmployeeList] = useState([]);
const addEmployee = () => {
Axios.post("http://localhost:3001/create", {
surename_ru: surename_ru,
name_ru: name_ru,
fname_ru: fname_ru,
surename_en: surename_en,
name_en: name_en,
gender: gender,
dateofbirth: dateofbirth,
citizenship: citizenship,
pas_ser: pas_ser,
pas_num: pas_num,
pas_start: pas_start,
pas_end: pas_end,
pas_given: pas_given,
pas_givenkod: pas_givenkod,
inn_num: inn_num,
snils_num: snils_num,
legal_type: legal_type,
}).then(() => {
setEmployeeList([
...employeeList,
{
surename_ru: surename_ru,
name_ru: name_ru,
fname_ru: fname_ru,
surename_en: surename_en,
name_en: name_en,
gender: gender,
dateofbirth: dateofbirth,
citizenship: citizenship,
pas_ser: pas_ser,
pas_num: pas_num,
pas_start: pas_start,
pas_end: pas_end,
pas_given: pas_given,
pas_givenkod: pas_givenkod,
inn_num: inn_num,
snils_num: snils_num,
legal_type: legal_type,
},
]);
});
};
const getEmployees = () => {
Axios.get("http://localhost:3001/employees").then((response) => {
setEmployeeList(response.data);
});
};
const updateEmployeeWage = (id) => {
Axios.put("http://localhost:3001/update", { wage: newWage, id: id }).then(
(response) => {
setEmployeeList(
employeeList.map((val) => {
return val.id == id
? {
surename_ru: val.surename_ru,
name_ru: val.name_ru,
fname_ru: val.fname_ru,
surename_en: val.surename_en,
name_en: val.name_en,
gender: val.gender,
dateofbirth: val.dateofbirth,
citizenship: val.citizenship,
pas_ser: val.pas_ser,
pas_num: val.pas_num,
pas_start: val.pas_start,
pas_end: val.pas_end,
pas_given: val.pas_given,
pas_givenkod: val.pas_givenkod,
inn_num: val.inn_num,
snils_num: val.snils_num,
legal_type: val.legal_type,
}
: val;
})
);
}
);
};
const deleteEmployee = (id) => {
Axios.delete(`http://localhost:3001/delete/${id}`).then((response) => {
setEmployeeList(
employeeList.filter((val) => {
return val.id != id;
})
);
});
};
return (
<div className="App">
<div className="information">
<label>Фамилия</label>
<input
type="text"
onChange={(event) => {
setSurename_ru(event.target.value);
}}
/>
<label>Имя РУС</label>
<input
type="text"
onChange={(event) => {
setName_ru(event.target.value);
}}
/>
<label>Отчество</label>
<input
type="text"
onChange={(event) => {
setFname_ru(event.target.value);
}}
/>
<label>Surename EN</label>
<input
type="text"
onChange={(event) => {
setSurename_en(event.target.value);
}}
/>
<label>Name EN</label>
<input
type="text"
onChange={(event) => {
setName_en(event.target.value);
}}
/>
<label>gender</label>
<input
type="text"
onChange={(event) => {
setGender(event.target.value);
}}
/>
<label>Data ROJD</label>
<input
type="text"
onChange={(event) => {
setDateofbirth(event.target.value);
}}
/>
<label>Citizenship</label>
<input
type="text"
onChange={(event) => {
setCitizenship(event.target.value);
}}
/>
<label>Pas SER</label>
<input
type="text"
onChange={(event) => {
setPas_ser(event.target.value);
}}
/>
<label>Pas NUM</label>
<input
type="text"
onChange={(event) => {
setPas_num(event.target.value);
}}
/>
<label>Pas Start</label>
<input
type="text"
onChange={(event) => {
setPas_start(event.target.value);
}}
/>
<label>Pas End</label>
<input
type="text"
onChange={(event) => {
setPas_end(event.target.value);
}}
/>
<label>Pas Given</label>
<input
type="text"
onChange={(event) => {
setPas_given(event.target.value);
}}
/>
<label>Pas Givenkod</label>
<input
type="text"
onChange={(event) => {
setPas_givenkod(event.target.value);
}}
/>
<label>inn_num</label>
<input
type="text"
onChange={(event) => {
setInn_num(event.target.value);
}}
/>
<label>snils_num</label>
<input
type="text"
onChange={(event) => {
setSnils_num(event.target.value);
}}
/>
<label>legal Type</label>
<input
type="text"
onChange={(event) => {
setLegal_type(event.target.value);
}}
/>
<button onClick={addEmployee}>Add Employee</button>
</div>
<div className="employees">
<button onClick={getEmployees}>Show Employees</button>
{employeeList.map((val, key) => {
return (
<div className="employee">
<div>
<h3>surename_ru: val.surename_ru</h3>
<h3>name_ru: val.name_ru</h3>
<h3>fname_ru: val.fname_ru</h3>
<h3>surename_en: val.surename_en</h3>
<h3>name_en: val.name_en</h3>
<h3>gender: val.gender</h3>
<h3>dateofbirth: val.dateofbirth</h3>
<h3>citizenship: val.citizenship</h3>
<h3>pas_ser: val.pas_ser</h3>
<h3>pas_num: val.pas_num</h3>
<h3>pas_start: val.pas_start</h3>
<h3>pas_end: val.pas_end</h3>
<h3>pas_given: val.pas_given</h3>
<h3>pas_givenkod: val.pas_givenkod</h3>
<h3>inn_num: val.inn_num</h3>
<h3>snils_num: val.snils_num</h3>
<h3>legal_type: val.legal_type</h3>
</div>
<div>
<input
type="text"
placeholder="2000..."
onChange={(event) => {
setNewWage(event.target.value);
}}
/>
<button variant="primary"
onClick={() => {
updateEmployeeWage(val.id);
}}
>
{" "}
Update
</button>
<button variant="primary"
onClick={() => {
deleteEmployee(val.id);
}}
>
Delete
</button>
</div>
</div>
);
})}
</div>
</div>
);
}
)
}
export default newcreate;
\add.js
import React, { Component } from 'react';
import newcreate from './addpeople';
function add() {
return (
<div>
<div>
<newcreate />
</div>
</div>
);
}
export default add;
You are trying to return hooks and functions from a functions return(). But instead you need to do that outside of return, so that your logic works. You can refer react hook docs here: https://reactjs.org/docs/hooks-overview.html#:~:text=Hooks%20are%20functions%20that%20let,if%20you'd%20like.)
For your code you can try something like this:
import React, { Component } from "react";
import "./add.css";
import { useState } from "react";
import Axios from "axios";
import { Button } from "react-bootstrap";
import "bootstrap/dist/css/bootstrap.min.css";
function newcreate() {
function App() {
const [surename_ru, setSurename_ru] = useState("");
const [name_ru, setName_ru] = useState(0);
const [fname_ru, setFname_ru] = useState("");
const [surename_en, setSurename_en] = useState("");
const [name_en, setName_en] = useState(0);
const [gender, setGender] = useState("");
const [dateofbirth, setDateofbirth] = useState(0);
const [citizenship, setCitizenship] = useState("");
const [pas_ser, setPas_ser] = useState("");
const [pas_num, setPas_num] = useState(0);
const [pas_start, setPas_start] = useState("");
const [pas_end, setPas_end] = useState(0);
const [pas_given, setPas_given] = useState("");
const [pas_givenkod, setPas_givenkod] = useState("");
const [inn_num, setInn_num] = useState(0);
const [snils_num, setSnils_num] = useState("");
const [legal_type, setLegal_type] = useState(0);
const [newWage, setNewWage] = useState(0);
const [employeeList, setEmployeeList] = useState([]);
const addEmployee = () => {
Axios.post("http://localhost:3001/create", {
surename_ru: surename_ru,
name_ru: name_ru,
fname_ru: fname_ru,
surename_en: surename_en,
name_en: name_en,
gender: gender,
dateofbirth: dateofbirth,
citizenship: citizenship,
pas_ser: pas_ser,
pas_num: pas_num,
pas_start: pas_start,
pas_end: pas_end,
pas_given: pas_given,
pas_givenkod: pas_givenkod,
inn_num: inn_num,
snils_num: snils_num,
legal_type: legal_type,
}).then(() => {
setEmployeeList([
...employeeList,
{
surename_ru: surename_ru,
name_ru: name_ru,
fname_ru: fname_ru,
surename_en: surename_en,
name_en: name_en,
gender: gender,
dateofbirth: dateofbirth,
citizenship: citizenship,
pas_ser: pas_ser,
pas_num: pas_num,
pas_start: pas_start,
pas_end: pas_end,
pas_given: pas_given,
pas_givenkod: pas_givenkod,
inn_num: inn_num,
snils_num: snils_num,
legal_type: legal_type,
},
]);
});
};
const getEmployees = () => {
Axios.get("http://localhost:3001/employees").then((response) => {
setEmployeeList(response.data);
});
};
const updateEmployeeWage = (id) => {
Axios.put("http://localhost:3001/update", { wage: newWage, id: id }).then(
(response) => {
setEmployeeList(
employeeList.map((val) => {
return val.id == id
? {
surename_ru: val.surename_ru,
name_ru: val.name_ru,
fname_ru: val.fname_ru,
surename_en: val.surename_en,
name_en: val.name_en,
gender: val.gender,
dateofbirth: val.dateofbirth,
citizenship: val.citizenship,
pas_ser: val.pas_ser,
pas_num: val.pas_num,
pas_start: val.pas_start,
pas_end: val.pas_end,
pas_given: val.pas_given,
pas_givenkod: val.pas_givenkod,
inn_num: val.inn_num,
snils_num: val.snils_num,
legal_type: val.legal_type,
}
: val;
})
);
}
);
};
const deleteEmployee = (id) => {
Axios.delete(`http://localhost:3001/delete/${id}`).then((response) => {
setEmployeeList(
employeeList.filter((val) => {
return val.id != id;
})
);
});
};
return (
<div className="App">
<div className="information">
<label>Фамилия</label>
<input
type="text"
onChange={(event) => {
setSurename_ru(event.target.value);
}}
/>
<label>Имя РУС</label>
<input
type="text"
onChange={(event) => {
setName_ru(event.target.value);
}}
/>
<label>Отчество</label>
<input
type="text"
onChange={(event) => {
setFname_ru(event.target.value);
}}
/>
<label>Surename EN</label>
<input
type="text"
onChange={(event) => {
setSurename_en(event.target.value);
}}
/>
<label>Name EN</label>
<input
type="text"
onChange={(event) => {
setName_en(event.target.value);
}}
/>
<label>gender</label>
<input
type="text"
onChange={(event) => {
setGender(event.target.value);
}}
/>
<label>Data ROJD</label>
<input
type="text"
onChange={(event) => {
setDateofbirth(event.target.value);
}}
/>
<label>Citizenship</label>
<input
type="text"
onChange={(event) => {
setCitizenship(event.target.value);
}}
/>
<label>Pas SER</label>
<input
type="text"
onChange={(event) => {
setPas_ser(event.target.value);
}}
/>
<label>Pas NUM</label>
<input
type="text"
onChange={(event) => {
setPas_num(event.target.value);
}}
/>
<label>Pas Start</label>
<input
type="text"
onChange={(event) => {
setPas_start(event.target.value);
}}
/>
<label>Pas End</label>
<input
type="text"
onChange={(event) => {
setPas_end(event.target.value);
}}
/>
<label>Pas Given</label>
<input
type="text"
onChange={(event) => {
setPas_given(event.target.value);
}}
/>
<label>Pas Givenkod</label>
<input
type="text"
onChange={(event) => {
setPas_givenkod(event.target.value);
}}
/>
<label>inn_num</label>
<input
type="text"
onChange={(event) => {
setInn_num(event.target.value);
}}
/>
<label>snils_num</label>
<input
type="text"
onChange={(event) => {
setSnils_num(event.target.value);
}}
/>
<label>legal Type</label>
<input
type="text"
onChange={(event) => {
setLegal_type(event.target.value);
}}
/>
<button onClick={addEmployee}>Add Employee</button>
</div>
<div className="employees">
<button onClick={getEmployees}>Show Employees</button>
{employeeList.map((val, key) => {
return (
<div className="employee">
<div>
<h3>surename_ru: val.surename_ru</h3>
<h3>name_ru: val.name_ru</h3>
<h3>fname_ru: val.fname_ru</h3>
<h3>surename_en: val.surename_en</h3>
<h3>name_en: val.name_en</h3>
<h3>gender: val.gender</h3>
<h3>dateofbirth: val.dateofbirth</h3>
<h3>citizenship: val.citizenship</h3>
<h3>pas_ser: val.pas_ser</h3>
<h3>pas_num: val.pas_num</h3>
<h3>pas_start: val.pas_start</h3>
<h3>pas_end: val.pas_end</h3>
<h3>pas_given: val.pas_given</h3>
<h3>pas_givenkod: val.pas_givenkod</h3>
<h3>inn_num: val.inn_num</h3>
<h3>snils_num: val.snils_num</h3>
<h3>legal_type: val.legal_type</h3>
</div>
<div>
<input
type="text"
placeholder="2000..."
onChange={(event) => {
setNewWage(event.target.value);
}}
/>
<button
variant="primary"
onClick={() => {
updateEmployeeWage(val.id);
}}
>
{" "}
Update
</button>
<button
variant="primary"
onClick={() => {
deleteEmployee(val.id);
}}
>
Delete
</button>
</div>
</div>
);
})}
</div>
</div>
);
}
}
Hope this helps!
function App() {
const [surename_ru, setSurename_ru] = useState("");
const [name_ru, setName_ru] = useState(0);
const [fname_ru, setFname_ru] = useState("");
const [surename_en, setSurename_en] = useState("");
const [name_en, setName_en] = useState(0)....
export default App;
Problem solved, thanks.

I am not getting synthetic event while using in onChange in react js

I am trying to select the product in the dropdown menu and increase the quantity as well. But I am unable to select them. In the onChange function, the event object I am getting is undefined. And an error is as follows.
Uncaught TypeError: Cannot read properties of undefined (reading
'name')
And code as follows:
import React, { useEffect, useState } from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { startCraeteBill } from '../../actions/billAction'
import Select from 'react-select'
import BillsList from './BillsList'
const AddBill = (props) => {
const customers = useSelector(state => state.customers)
const products = useSelector(state => state.products)
const dispatch = useDispatch()
const [formValues, setFormValues] = useState([{ product: "", quantity: 1 }])
const [_id, set_Id] = useState('')
const [cust, setCust] = useState('')
const [total, setTotal] = useState(0)
const handleChange = (e, i) => {
const newFormvalues = [...formValues]
console.log('e', e, i)
newFormvalues[i][e.target.name] = e.target.value
console.log('add bill', newFormvalues)
setFormValues(newFormvalues)
}
const addFormFields = () => {
const newFormvalues = [...formValues, { product: '', quantity: 1 }]
setFormValues(newFormvalues)
}
const removeFormFields = (i) => {
const newFormvalues = formValues.filter((ele, index) => { return index !== i })
setFormValues(newFormvalues)
}
const handleSubmit = (e) => {
e.preventDefault()
const todayDate = new Date().toISOString.slice(0, 10)
const formData = {
date: todayDate, customer: _id, lineItems: [...formValues]
}
dispatch(startCraeteBill(formData, resetForm))
setTotal(0)
}
const subTotalFun = (product, quantity) => {
return products.data.find(ele => ele._id === product).price * quantity
}
const handleId = (cust) => {
setCust(cust)
set_Id(cust._id)
}
const resetForm = () => {
setFormValues([{ product: '', quantity: 1 }])
set_Id('')
}
console.log('form values', formValues)
useEffect(() => {
if (formValues.every(ele => ele.product)) {
let total = 0
formValues.forEach(ele => { total += subTotalFun(ele.product, ele.quantity) })
setTotal(total)
}
}, [formValues])
return (<div>
<div className="border shadow rounded p-2" style={{ color: '#66FCF1', backgroundColor: '#2F363F' }}>
<h2 className=" d-inline">Add Bills</h2><h2 className="d-inline m-3" style={{ float: 'right' }}>Total:{total}</h2>
<form onSubmit={handleSubmit}>
<div style={{ width: '40%', color: 'black' }} className="m-2">
<Select name="customer" options={customers.data} placeholder="--Select Customer--" value={customers.data.filter(function (option) {
return option.name === cust.name
})} getOptionLabel={(option) => option.name} label={(option) => option.name}
getOptionValue={(option) => option._id}
onChange={handleId}
/>
</div>
{
formValues.map((ele, index) => (
<div className="form-inline " key={index}>
<select className='form-select d-inline m-2' name='product' value={ele.product || ''} style={{ width: '40%' }} onChange={() => {handleChange(index)}}>
<option>--Select Product--</option>
{
products.data.map((ele, i) => {
return <option key={ele._id} value={ele._id}>{ele.name}</option>
})
}
</select>
<input type='number' className="form-control d-inline m-2 " name='quantity' min="1" max="99" placeholder="Quantity" value={ele.quantity || ""} onChange={() => {handleChange(index)}} style={{ width: '20%' }} />
{ele.product && <h5 className="d-inline p-2">{subTotalFun(ele.product, ele.quantity)}</h5>}
{
index ? <button type="button" className="button remove btn btn-danger m-2 " onClick={() => removeFormFields(index)}>Remove</button>
: null
}
</div>
))
}
<div className="botton-section">
<button className="button add btn btn-warning m-2" onClick={() => addFormFields()}>Add</button>
<button className="button submit btn btn-primary m-2" type="submit">Submit</button>
</div>
</form>
<div>
<BillsList _id={_id} />
</div>
</div>
</div>)
}
export default AddBill
this is the error I am getting while selecting from the dropdown
You are not passing event as a parameter in your onChange function
onChange((e) => handleChange(e, index))

creating unique id into object without UUID in React

I am trying to test my understanding of React but hit a mental block. Would it be possible to create a unique key / id within my <FormInput> component rather than creating the unique ID inside the <MainUI> component once the newly created item is passed up into <MainUI>? I find that weird and definitely feel like there is a way better method of doing this.
const MainUI = props => {
const receiveNewItem = enteredNewItem => {
const newItem = {
...enteredNewItem,
id: Math.random().toString()
}
props.addNewItem(newItem)
}
console.log(props.data)
return(
<div>
<FormInput receiveNewItem={receiveNewItem}/>
{/* <MaxAmount data={props.data} /> */}
<DisplayItems data={props.data} key={props.data.id} />
</div>
)
}
export default MainUI;
import { useState } from 'react'
import Card from './Card'
const FormInput = props => {
const [userInput, setUserInput] = useState({
name: '',
amount: '',
date: ''
})
const nameInputHandler = e => {
setUserInput( prevObj => {
return {...prevObj, name: e.target.value}
})
}
const amountInputHandler = e => {
setUserInput( prevObj => {
return {...prevObj, amount: e.target.value}
})
}
const dateInputHandler = e => {
setUserInput( prevObj => {
return {...prevObj, date: e.target.value}
})
}
const submitHandler = e => {
e.preventDefault()
props.receiveNewItem(userInput)
setUserInput( prevObj => { return {...prevObj, name: ''}})
}
return (
<Card>
<form onSubmit={submitHandler}>
<input
type="text"
placeholder="Name Input"
value={userInput.name}
onChange={nameInputHandler} />
<input
type="number"
placeholder="Amount Input"
value={userInput.amount}
onChange={amountInputHandler} />
<input
type="date"
placeholder="Date Input"
value={userInput.date}
onChange={dateInputHandler} />
<button>Add Item</button>
</form>
</Card>
)
}
export default FormInput;

How to display updated user values?

<-- Whenever I try to update user info,I am not getting the updated values.But when I reload the page,I get the updated values.Is there a way to get the updated values whenever I hit the update button which is in MiddlePanel? Right now I am fetching all users in loadUsers. -->
class Home extends Component {
state = {
loadUsers: [],
currentUser: null,
};
async componentDidMount() {
const res = await axios.get("http://localhost:5000/users");
this.setState({ loadUsers: res.data });
}
setUser = (currentUser) => {
this.setState({ currentUser });
};
render() {
return (
<Fragment>
<div className="row">
<div className="col-md-3" style={{ backgroundColor: "#303F9F" }}>
<Typography variant="h6">List all Counsellors</Typography>
{this.state.loadUsers.map((user) => {
const { _id, firstname, lastname } = user;
return (
<div key={_id}>
<PrimaryButton
onClick={(e) => {
this.setUser(user);
}}
>
{firstname} {lastname}
</PrimaryButton>
</div>
);
})}
</div>
<div className="col-md-4">
{this.state.currentUser && (
<div>
<MiddlePanel user={this.state.currentUser} />
</div>
)}
</div>
</div>
</Fragment>
);
}
}
export default Home;
Here is my middlepanel code
const MiddlePanel = ({ user }) => {
const [data, setData] = useState({
firstname: "",
lastname: "",
email: "",
phoneNo: "",
});
const { firstname, lastname, email, phoneNo } = data;
useEffect(() => {
const fetchUser = async () => {
const res = await axios.get(`http://localhost:5000/users/${user._id}`);
setData({
firstname: res.data.firstname,
lastname: res.data.lastname,
email: res.data.email,
phoneNo: res.data.phoneNo,
});
};
fetchUser();
}, [user._id]);
const handleChange = (e) => {
const { name, value } = e.target;
setData({ ...data, [name]: value });
};
const handleSubmit = async (e) => {
e.preventDefault();
const newUser = { firstname, lastname, email, phoneNo };
try {
const config = {
headers: {
"Content-Type": "application/json",
},
};
const body = JSON.stringify(newUser);
await axios.patch(
`http://localhost:5000/users/${user._id}`,
body,
config
);
} catch (err) {
console.log(err);
}
};
return (
<div>
<Form onSubmit={handleSubmit}>
<Input
type="text"
name="firstname"
onChange={handleChange}
value={data.firstname}
/>
<Input
type="text"
name="lastname"
onChange={handleChange}
value={data.lastname}
/>
<Input
type="email"
name="email"
onChange={handleChange}
value={data.email}
/>
<Input
type="tel"
name="phoneNo"
onChange={handleChange}
value={data.phoneNo}
/>
<PrimaryButton>Update</PrimaryButton>
</Form>
</div>
);
};
I want to display the updated user info which I am doing in the Middlepanel
try this code , I tested this in codesandbox it works
import React, { Component, Fragment } from "react";
import axios from "axios";
class Home extends Component {
state = {
loadUsers: [],
currentUser: null
};
async componentDidMount() {
const res = await axios.get("https://reqres.in/api/users?page=2");
this.setState({ loadUsers: res.data.data });
}
setUser = (currentUser) => {
console.log(currentUser);
this.setState({ currentUser });
};
render() {
return (
<Fragment>
<div className="row">
<div className="col-md-3" style={{ backgroundColor: "#303F9F" }}>
{/* <Typography variant="h6">List all Counsellors</Typography> */}
{this.state.loadUsers
? this.state.loadUsers.map((user) => {
const { _id, first_name, lastname } = user;
return (
<div key={_id}>
<button onClick={()=> this.setUser(first_name)}>
{first_name} {lastname}
</button>
</div>
);
})
: null}
</div>
<div className="col-md-4">
{this.state.currentUser && <div>{this.state.currentUser}</div>}
</div>
</div>
</Fragment>
);
}
}
export default Home;

React Required Input

I'm trying to require the name and email in my form. I originally had <button> nested within a <Link> and figured out that the <button> worked by itself to allow the input to be required, but that when it's nested within the <Link> it doesn't require it. I then added the link to be within the submitSurvey function and took the <Link> away from the render. It still won't require the input.
Here is my NameEmailComponent.js:
import React, { useState } from "react";
import { NameInput } from "../inputs/NameInput";
import { EmailInput } from "../inputs/EmailInput";
import { useHistory } from "react-router-dom";
export const NameEmailComponent = (props) => {
const [surveyValues, setSurveyValues] = useState({});
const [inlineData, setInlineData] = useState({});
const [question, setQuestion] = useState({});
const history = useHistory();
console.log(props);
const triggerBackendUpdate = () => {
setSurveyValues({});
setQuestion({});
};
const handleSubmit = (event) => {
event.preventDefault();
event.persist();
setSurveyValues(surveyValues);
setQuestion(question);
triggerBackendUpdate();
};
const callback = (name, value) => {
console.log("Form Data: ", name, ": ", value);
inlineData[name] = value;
setInlineData(inlineData);
console.log(inlineData);
};
const handleChange = (event) => {
event.preventDefault();
this.setState({ value: event.target.value });
console.log("Name: ", event.target.value);
};
const submitSurvey = async () => {
try {
await fetch("/api/survey", {
method: "POST",
body: JSON.stringify(inlineData),
headers: {
"Content-Type": "application/json",
},
});
history.push({ pathname: "/survey" });
} catch (err) {
console.log(err);
}
};
const inputs = props.inputs
? props.inputs.filter((inputOption) => inputOption)
: [];
return (
<>
<div id="nameContainer" className="form-group">
<form onSubmit={handleSubmit}>
{inputs.map((data, index) => {
let inputKey = `input-${index}`;
return data.type === "text" ? (
<NameInput
className="form-control my-3"
triggerCallback={callback}
name={data.name}
type={data.type}
placeholder={data.placeholder}
required={true}
onChange={handleChange}
key={inputKey}
/>
) : (
<EmailInput
className="form-control mt-3"
triggerCallback={callback}
name={data.name}
type={data.type}
placeholder={data.placeholder}
required={true}
onChange={handleChange}
key={inputKey}
/>
);
})}
<div className="col-6 mx-auto text-center">
<div className="button">
<button
className="btn btn-primary mt-4 mb-2 mx-5"
type="submit"
onClick={submitSurvey}
>
Begin Survey
</button>
</div>
</div>
</form>
</div>
</>
);
};
Here is my NameInput.js:
import React from "react";
import { useInputChange } from "../Hooks/useInputChangeHook";
import { isTextInput } from "../validators";
export const NameInput = (props) => {
const inputType = isTextInput(props.type) ? props.type : "text";
const { handleChange } = useInputChange(
props.defaultValue,
props.triggerCallback,
inputType
);
const inputProps = {
className: props.className ? props.className : "form-control",
onChange: handleChange,
required: props.required,
question: props.question,
placeholder: props.placeholder,
type: inputType,
options: props.options,
name: props.name ? props.name : `${inputType}_${props.key}`,
};
return (
<>
<div id={props.name}>
<input
{...inputProps}
required={props.required}
value={props.value || ""}
/>
</div>
</>
);
};

Categories