简体   繁体   English

React - 更改组件内的 defaultValue 输入

[英]React - change defaultValue input inside a component

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如果我更改输入值并单击复制按钮(formItem.jsx),卡第一次完美复制,但是当我再次更改输入值并单击按钮复制时,新卡具有第一个值First值==>克隆第一个值==>第二个值==>克隆第二个值

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.如果我使用 value 和 onChange 而不是 defaultValue 和 onBlur 卡片会完美复制,但在我的项目中我需要很多卡片,因此我需要很多输入字段,但是如果我有很多输入,则使用 value 和 onChange,在输入时,有新文本在字段中显示的延迟最多为几秒钟。

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表单项.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>
)
}

The main problem is that the state for all the cards is stored in one place in the parent component.主要问题是所有卡的 state 都存储在父组件中的一个位置。 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.您将需要彻底重新考虑如何在此处存储 state。 I'm not going to write the code for you, but here's what you need to do:我不会为你编写代码,但这是你需要做的:

  • Move the value and onChange stuff into the FormItem component.valueonChange内容移动到 FormItem 组件中。 Each form item should be responsible for its own value and event handlers.每个表单项都应负责自己的值和事件处理程序。
  • Create a "form context" to wrap around all the form items ( read about react context here ).创建一个“表单上下文”来包裹所有表单项(在此处阅读有关反应上下文的信息)。 You should be able to save all of the values to this context, as well as any helper functions for cloning and such.您应该能够将所有值以及用于克隆等的任何辅助函数保存到此上下文中。 This will be useful for both cloning items and collecting all the values for all the inputs.这对于克隆项目和收集所有输入的所有值都很有用。
  • Find a better way to assign "keys" to your form items.找到一种更好的方法来为您的表单项分配“键”。 The same key should be assigned to the same form item even when new form items are added.即使添加了新的表单项,也应将相同的键分配给相同的表单项。 Using the index is not good enough.使用索引还不够好。 Imagine you have 3 form items and you clone the middle one, the last form item will get a new key when it really shouldn't.想象一下,您有 3 个表单项,并且您克隆了中间的一个,最后一个表单项将获得一个新密钥,而它确实不应该。 You need to generate a "id" for each form item and make sure that ID follows that form item even when new ones are added.您需要为每个表单项生成一个“id”,并确保即使添加了新的表单项,该 ID 也遵循该表单项。

Good luck.祝你好运。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM