Reputation: 3
If I change the input value and click the copy-button(formItem.jsx), the first time the card is duplicated perfectly, but when I change the input value again and click the button-copy the new card has the first one value First value ==> Cloning First value ==> Second value ==> Cloning Second value
If I use value and onChange instead of defaultValue and onBlur the card is duplicated perfectly, but in my project i will need many cards, therefore i will need many input fields, however using value and onChange if I have many inputs, when typing, there is a lag of up to several seconds for the new text to display in the field.
What can I do?
import "./header.css"
import React, { useState } from 'react';
import FormItem from './formItem'
export default (props) => {
const cardItemDefault = {
skin: '',
}
const [cardsItems, setCardsItems] = useState([])
const handleAddCardItem = () => {
setCardsItems([...cardsItems, cardItemDefault])
}
const handleRemoveCardItem = (index) => {
const values = [...cardsItems]
values.splice(index, 1)
setCardsItems([...values])
}
const handleChangeInput = (index, event) => {
const values = [...cardsItems]
values[index].skin = event.target.value
setCardsItems([...values])
}
const handleAddCopyCard = (index) => {
const values = [...cardsItems]
const copyCard = {
skin: values[index].skin,
}
values.splice(index+1, 0, copyCard)
setCardsItems([...values])
}
return (
<>
<nav className="NavbarItems">
<div className="marca">
<div className="menu-icon">
<img src="https://cdn.discordapp.com/attachments/825108658622955520/834516008982151178/image0.png" alt="catIcon"/>
</div>
<h1 className="navbar-logo">My project</h1>
</div>
<ul className="nav-menu">
<li>
<button className="button-addformItem" onClick={() => handleAddCardItem()}>Add</button>
</li>
</ul>
</nav>
<div className="container">
<div className="cards-items">
{cardsItems.map( (cardItem, index) => {
return (
<FormItem
key={index}
idItem={index}
skinCardItem={cardItem.skin}
onHandleRemoveCardItem={() => handleRemoveCardItem(index)}
onHandleChangeInput={(event) => handleChangeInput(index, event)}
onHandleClickCopy={() => handleAddCopyCard(index)}
/>
)
})}
</div>
</div>
</>
)
}
formItem.jsx
import "./formItem.css"
import React from 'react'
export default (props) => {
return (
<div className="card-formItem">
<div className="container-formItem">
<div className="header-formItem">
<i
className="fas fa-times fa-2x remove-item-button"
id={"remove-item-button" + props.idItem}
title='Remover item'
onClick={props.onHandleRemoveCardItem}
/>
</div>
<div className="formItem">
<div className="skin-input">
<input name="skin"
type="text"
placeholder="Skin"
defaultValue={props.skinCardItem}
onBlur={(event) => props.onHandleChangeInput(event)}
/>
</div>
</div>
</div>
<i
className="far fa-copy fa-2x copy-button"
id={"copy-button" + props.idItem}
onClick={() => props.onHandleClickCopy()}>
</i>
</div>
)
}
Upvotes: 0
Views: 195
Reputation: 28400
The main problem is that the state for all the cards is stored in one place in the parent component. This means that any time any input changes, ALL of the cards are re-rendered. You are going to need to drastically rethink how you store state here. I'm not going to write the code for you, but here's what you need to do:
value
and onChange
stuff into the FormItem component. Each form item should be responsible for its own value and event handlers.Good luck.
Upvotes: 0