creating unique id into object without UUID in React - javascript

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;

Related

react forms Controlled component

I am trying to make a form where inputs fields can be generated dynamically. While running it runs but react throws a warning about not being a controlled component. Any example for the solution I look online uses classes and constructors, is there any other way to do it without using classes?
import { useState } from 'react';
function Try() {
const [formFields, setFormFields] = useState([
{ StepNo: '', StepDisc: '' },
])
const handleFormChange = (event, index) => {
let data = [...formFields];
data[index][event.target.name] = event.target.value;
setFormFields(data);
}
const submit = (e) => {
e.preventDefault();
console.log(formFields)
}
const addFields = () => {
let object = {
StepNo: '',
StepDiscs: ''
}
setFormFields([...formFields, object])
}
const removeFields = (index) => {
let data = [...formFields];
data.splice(index, 1)
setFormFields(data)
}
return (
<div className="">
<form onSubmit={submit}>
{formFields.map((form, index) => {
return (
<div key={index}>
<input
name='StepNo'
placeholder='StepNo'
onChange={event => handleFormChange(event, index)}
value={form.StepNo}
/>
<input
name='StepDisc'
placeholder='StepDisc'
onChange={event => handleFormChange(event, index)}
value={form.StepDisc}
/>
<button onClick={() => removeFields(index)}>Remove</button>
</div>
)
})}
</form>
<button onClick={addFields}>Add More..</button>
<br />
<button onClick={submit}>Submit</button>
</div>
);
}
export default Try;
It's not related to the error you have, but I suggest you bind the key to a unique key as it can generate unpredictable issues when you remove the items.
const addFields = () => {
// Id should has a unique a id to be used in as a key.
const id = generateUniqueKey()
let object = {
StepNo: '',
StepDiscs: '',
id
}
setFormFields([...formFields, object])
}
{formFields.map((form, index) => {
return (
<div key={form.id}>
<input
name='StepNo'
placeholder='StepNo'
onChange={event => handleFormChange(event, index)}
value={form.StepNo}
/>
<input
name='StepDisc'
placeholder='StepDisc'
onChange={event => handleFormChange(event, index)}
value={form.StepDisc}
/>
<button onClick={() => removeFields(index)}>Remove</button>
</div>
)
})}
There's just typo in your code when you initialize new form data when adding. Instead of
let object = {
StepNo: '',
StepDiscs: ''
}
It should be
let object = {
StepNo: '',
StepDisc: ''
}
You need to change StepDiscs to StepDisc :-)
const addFields = () => {
let object = {
StepNo: '',
StepDiscs: ''
}

Add multiple input field dynamically in react

I have is a div that contains three input elements and a remove button. what is required is when the user clicks on the add button it will add this div dynamically and when the user clicks on the remove button it will remove this div. I was able to add one input element (without div container) dynamically with the following method.
create an array in the state variable.
assign a name to the dynamic input field with the help of array indexing like name0, name1
How can I do with these many input fields? The problem grows further when I create this whole div as a separate component. I am using a class-based component.
handleChange=(event) =>
{
this.setState({[event.target.name]:event.target.values});
}
render()
{
return(
<div className="row">
<button type="button" onClick={this.addElement}>Add</button>
<div className="col-md-12 form-group">
<input type="text" className="form-control" name="name" value={this.state.name} onChange={this.handleChange} />
<input type="text" className="form-control" name="email" value={this.state.email} onChange={this.handleChange} />
<input type="text" className="form-control" name="phone" value={this.state.phone} onChange={this.state.phone} />
<button type="button" onClick={this.removeElement}>Remove</button>
</div>
</div>
)
}
I would approach this from a configuration angle as it's a little more scalable. If you want to eventually change across to something like Formik or React Form, it makes the move a little easier.
Have an array of objects that you want to turn into input fields. Your main component should maintain state whether the <Form /> component is showing, and if it's visible pass in the config and any relevant handlers.
Your form component should maintain state for the inputs, and when you submit it, passes up the completed state to the parent.
const { Component } = React;
class Example extends Component {
constructor(props) {
super();
// The only state in the main component
// is whether the form is visible or not
this.state = { visible: false };
}
addForm = () => {
this.setState({ visible: true });
}
removeForm = () => {
this.setState({ visible: false });
}
handleSubmit = (form) => {
console.log(form);
}
render() {
const { visible } = this.state;
const { config } = this.props;
return (
<div>
<button
type="button"
onClick={this.addForm}
>Add form
</button>
{visible && (
<Form
config={config}
handleSubmit={this.handleSubmit}
handleClose={this.removeForm}
/>
)}
</div>
);
}
};
class Form extends Component {
constructor(props) {
super();
this.state = props.config.reduce((acc, c) => {
return { ...acc, [c.name]: '' };
}, {});
}
handleChange = (e) => {
const { name, value } = e.target;
this.setState({ [name]: value });
}
handleSubmit = () => {
this.props.handleSubmit(this.state);
}
render() {
const { name, email, phone } = this.state;
const { handleClose, config } = this.props;
return (
<div onChange={this.handleChange}>
{config.map(input => {
const { id, name, type, required } = input;
return (
<div>
<label>{name}</label>
<input key={id} name={name} type={type} required={required} />
</div>
)
})}
<button type="button" onClick={this.handleSubmit}>Submit form</button>
<button type="button" onClick={handleClose}>Remove form</button>
</div>
);
}
}
const config = [
{ id: 1, name: 'name', type: 'text', required: true },
{ id: 2, name: 'email', type: 'email', required: true },
{ id: 3, name: 'phone', type: 'phone', required: true }
];
ReactDOM.render(
<Example config={config} />,
document.getElementById('react')
);
input { display: block; }
label { text-transform: capitalize; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>
I hope this would be help for your question.
I made a child component which have three input tags.
// parent component
import React, { Component } from "react";
import TextField from "./TextField";
class App extends Component {
constructor(props) {
super(props);
this.state = {
users: [
{
key: Date.now(),
name: "",
email: "",
phone: ""
}
]
};
}
onChange = (inputUser) => {
this.setState((prevState) => {
const newUsers = prevState.users.map((element) => {
if (element.key === inputUser.key) return inputUser;
return element;
});
return { users: newUsers };
});
};
addElement = () => {
const { name, email, phone } = this.state;
this.setState((prevState) => ({
users: prevState.users.concat({
key: Date.now(),
name,
email,
phone
})
}));
};
removeElement = (id) => {
this.setState((prevState) => ({
users: prevState.users.filter((user) => user.key !== id)
}));
};
render() {
const { users } = this.state;
return (
<div className="row">
<button type="button" onClick={this.addElement}>
Add
</button>
<div className="col-md-12 form-group">
{users.map((user) => (
<React.Fragment key={user.key}>
<TextField
value={user}
onChange={(inputUser) => this.onChange(inputUser)}
/>
<button
type="button"
onClick={() => this.removeElement(user.key)}
disabled={users.length <= 1}
>
Remove
</button>
</React.Fragment>
))}
</div>
</div>
);
}
}
export default App;
// child component
import { Component } from "react";
class TextField extends Component {
handleChange = (ev) => {
const { name, value } = ev.target;
this.props.onChange({
...this.props.value,
[name]: value
});
};
render() {
const { value: user } = this.props;
return (
<>
<input
className="form-control"
name="name"
value={user.name}
onChange={this.handleChange}
placeholder="name"
type="text"
/>
<input
className="form-control"
name="email"
value={user.email}
onChange={this.handleChange}
placeholder="email"
type="text"
/>
<input
className="form-control"
name="phone"
value={user.phone}
onChange={this.handleChange}
placeholder="phone"
type="text"
/>
</>
);
}
}
export default TextField;
You can also check the code in codesandbox link below.
https://codesandbox.io/s/suspicious-heisenberg-xzchm
It was a little difficult to write down every detail of how to generate what you want. So I find it much easier to ready a stackblitz link for you to see how is it going to do this and the link is ready below:
generating a dynamic div adding and removing by handling inputs state value
const { Component } = React;
class Example extends Component {
constructor(props) {
super();
// The only state in the main component
// is whether the form is visible or not
this.state = { visible: false };
}
addForm = () => {
this.setState({ visible: true });
}
removeForm = () => {
this.setState({ visible: false });
}
handleSubmit = (form) => {
console.log(form);
}
render() {
const { visible } = this.state;
const { config } = this.props;
return (
<div>
<button
type="button"
onClick={this.addForm}
>Add form
</button>
{visible && (
<Form
config={config}
handleSubmit={this.handleSubmit}
handleClose={this.removeForm}
/>
)}
</div>
);
}
};
class Form extends Component {
constructor(props) {
super();
this.state = props.config.reduce((acc, c) => {
return { ...acc, [c.name]: '' };
}, {});
}
handleChange = (e) => {
const { name, value } = e.target;
this.setState({ [name]: value });
}
handleSubmit = () => {
this.props.handleSubmit(this.state);
}
render() {
const { name, email, phone } = this.state;
const { handleClose, config } = this.props;
return (
<div onChange={this.handleChange}>
{config.map(input => {
const { id, name, type, required } = input;
return (
<div>
<label>{name}</label>
<input key={id} name={name} type={type} required={required} />
</div>
)
})}
<button type="button" onClick={this.handleSubmit}>Submit form</button>
<button type="button" onClick={handleClose}>Remove form</button>
</div>
);
}
}
const config = [
{ id: 1, name: 'name', type: 'text', required: true },
{ id: 2, name: 'email', type: 'email', required: true },
{ id: 3, name: 'phone', type: 'phone', required: true }
];
ReactDOM.render(
<Example config={config} />,
document.getElementById('react')
);
input { display: block; }
label { text-transform: capitalize; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>

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

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;

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>
</>
);
};

Show the next data while looping over an array in typescript react

So, I am trying to add some data to two different array in react typescript
const [deviceNames, setDeviceNames] = useState<Array<string>>([])
const [serialNumbers, setSerialNumbers] = useState<Array<string>>([])
I am now looping over both the array here and displaying the content
{deviceNames.length > 0 &&
serialNumbers.length > 0 &&
deviceNames.map(deviceName => {
return serialNumbers.map(serialNumber => {
return (
<CardDevice
deviceName={deviceName}
serialNumber={serialNumber}
/>
)
})
})}
I am adding data to these array by clicking on a button and then showing modal and then like this
onSubmit = (values: any) => {
clearError()
setAddDevice(false)
setDeviceNames(deviceName => [...deviceName, values.deviceName])
setSerialNumbers(serialNumber => [...serialNumber, values.serialNumber])
}
I am using react hook form.
So what i want is whenever i loop over both the arrays, each time it should display the content which was just added in the array the new one not the last one again which was already added and displayed. I hope i am able to make some point here. It does the job but whenever user enters new device after adding one, it add the old one again and then the new one and then again and then again same thing.
i just want to display just one new item which was just last added to an array by the user.
Thanks
Basically i answered my own question:
import React, { useState } from "react";
function App() {
const [addCardData, setAddCardData] = useState("");
const [addCards, setAddCards] = useState<Array<string>>([]);
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setAddCardData(event.target.value);
};
const handleSubmit = (event: React.FormEvent<HTMLFormElement>): void => {
event.preventDefault();
setAddCards(prevState => [...prevState, addCardData]);
};
return (
<div
className="App"
style={{ textAlign: "center", margin: "0 auto", marginTop: "10em" }}
>
<form onSubmit={handleSubmit}>
<input type="text" onChange={handleChange} placeholder="Add any text" />
<button type="submit">Add</button>
</form>
{addCards.map(addCard => (
<h3>{addCard}</h3>
))}
</div>
);
}
export default App;
Here is some more Dynamic Approach:
import React, { useState } from "react";
import { TextInput } from "./components/TextInput";
interface Device {
deviceName: string;
serialNumber: string | number;
}
const App: React.FC = () => {
const [deviceName, setDeviceName] = useState("");
const [serialNumber, setSerialNumber] = useState("");
const [deviceInfos, setDeviceInfos] = useState<Device[]>([]);
const handleDeviceChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setDeviceName(event.target.value);
};
const handleSerialChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setSerialNumber(event.target.value);
};
const handleSubmit = (event: React.FormEvent<HTMLFormElement>): void => {
event.preventDefault();
addDevice();
setDeviceName("");
setSerialNumber("");
};
const addDevice = () => {
const newDevice: Device[] = [
...deviceInfos,
{ deviceName: deviceName, serialNumber: serialNumber }
];
setDeviceInfos(newDevice);
};
return (
<div
className="App"
style={{ textAlign: "center", margin: "0 auto", marginTop: "10em" }}
>
<form onSubmit={handleSubmit}>
<TextInput
type="text"
placeholder="Add Device Name"
handleChange={handleDeviceChange}
value={deviceName}
/>
<TextInput
type="text"
placeholder="Add fuck"
handleChange={handleSerialChange}
value={serialNumber}
/>
<button type="submit">Add</button>
</form>
{deviceInfos.map((device, i) => (
<div key={i}>
<h3>{device.deviceName}</h3>
<h3>{device.serialNumber}</h3>
</div>
))}
</div>
);
};
export default App;
Much Better Approach i used in the production
const ProfileDevices: React.FC<Props> = ({ onSubmit }) => {
const [addDevice, setAddDevice] = useState(false)
const [deviceInfos, setDeviceInfos] = useState<Device[]>([])
const { register, handleSubmit, errors, clearError } = useForm({
mode: 'onSubmit',
})
const addDevices: any = () => {
setAddDevice(true)
}
onSubmit = (values: any) => {
clearError()
setAddDevice(false)
const newDevice: Device[] = [
...deviceInfos,
{ deviceName: values.deviceName, serialNumber: values.serialNumber },
]
setDeviceInfos(newDevice)
}
return (
<ProfileContentContainer>
<ProfileHeader>
<ProfileTitle>Devices</ProfileTitle>
<ProfileActions>
<Button
type="button"
bgType="fill"
size="default"
label="Add Device"
onClick={addDevices}
/>
</ProfileActions>
</ProfileHeader>
{console.log(deviceInfos)}
<DeviceList>
<CardDevice deviceName="Device Name" serialNumber="QR10001123456788" />
<CardDevice deviceName="Device Name" serialNumber="QR10001123456789" />
{deviceInfos.map((device, i) => (
<CardDevice
key={i}
deviceName={device.deviceName}
serialNumber={device.serialNumber}
/>
))}
</DeviceList>
<Modal isActive={addDevice} toggleModal={() => setAddDevice(false)}>
<ModalContent>
<ModalHeader title="Add Device" />
<AuthForm
onSubmit={handleSubmit(onSubmit)}
className="modalAddDeviceForm"
>
<InputText
placeholder="DeviceName"
name="deviceName"
type="text"
register={register({ required: true, maxLength: 10 })}
hasError={errors.deviceName}
errorMessage={
errors.serialNumber ? errors.serialNumber.message : undefined
}
/>
<InputText
placeholder="Serial Number"
name="serialNumber"
type="text"
register={register({ required: true, maxLength: 10 })}
hasError={errors.serialNumber}
errorMessage={
errors.serialNumber ? errors.serialNumber.message : undefined
}
/>
<Button type="submit" bgType="fill" size="default" label="Add" />
</AuthForm>
<ModalActions></ModalActions>
</ModalContent>
</Modal>
</ProfileContentContainer>
)
}
export default ProfileDevices

Categories