Estoy creando un elemento de reacción que permite a los usuarios enviar correos electrónicos a amigos/familiares. El elemento tiene por defecto 3 campos de entrada; sin embargo, el usuario puede hacer clic en un botón para agregar campos de entrada adicionales.
Mi idea para construir este componente es tener un botón que incremente un contador y luego usar ese valor de contador para ejecutar un ciclo y agregar elementos a una matriz.
<button onClick={handleAddEmail}> Add email </button> function handleAddEmail() { setNumberOfEmails(numberOfEmails + 1); } Ahora, para que esto funcione, necesito un gancho NumberOfEmails . Este enlace se inicializará con los tres primeros campos de entrada.
const [numberOfEmails, setNumberOfEmails] = useState(3); Además, hay un gancho inviteEmails para manejar el estado de cada entrada.
const [inviteEmails, setInviteEmails] = useState([])Todas estas entradas deben representarse en una función:
function renderEmailFields() { const emailContainer = [ <input value={inviteEmails[0]} onChange={(e) => handleEmailChange(0, e)} placeholder="Enter email here..." />, <input value={inviteEmails[1]} onChange={(e) => handleEmailChange(1, e)} placeholder="Enter email here..." />, <input value={inviteEmails[2]} onChange={(e) => handleEmailChange(2, e)} placeholder="Enter email here..." />]; for (let i = 3; i < numberOfEmails; i++) { emailContainer.push( <input value={inviteEmails[i]} onChange={(e) => handleEmailChange(i, e)} placeholder="New email..." /> ); } return emailContainer;El código que tengo arriba está cerca de funcionar, sin embargo, agregar un nuevo campo de entrada hace que las entradas anteriores se bloqueen y no se puedan editar.
Cualquier consejo sería apreciado.
Realmente no necesita un segundo átomo de estado para la cantidad de entradas si me pregunta.
Vea CodeSandbox en vivo aquí .
useCallback y la magia del dataset de datos hacen que no necesite una función de controlador onClick separada para cada entrada..filter(Boolean) elimina todos los valores falsos; las cadenas vacías son falsas. function App() { const [inviteEmails, setInviteEmails] = React.useState(["", "", ""]); const handleEmailChange = React.useCallback((event) => { const index = parseInt(event.target.dataset.index, 10); setInviteEmails((inviteEmails) => { const newInviteEmails = [...inviteEmails]; newInviteEmails[index] = event.target.value; return newInviteEmails; }); }, []); const removeEmail = React.useCallback((event) => { const index = parseInt(event.target.dataset.index, 10); setInviteEmails((inviteEmails) => { const newInviteEmails = [...inviteEmails]; newInviteEmails.splice(index, 1); return newInviteEmails; }); }, []); const addEmail = React.useCallback( () => setInviteEmails((inviteEmails) => [...inviteEmails, ""]), [] ); return ( <div> {inviteEmails.map((email, index) => ( <div key={index}> <input value={email} data-index={index} onChange={handleEmailChange} placeholder="Enter email here..." /> <button onClick={removeEmail} data-index={index}> × </button> </div> ))} <button onClick={addEmail}>Add email</button> <pre>{JSON.stringify(inviteEmails.filter(Boolean), null, 2)}</pre> </div> ); }