I'm once again here asking for help, I have this component that renders an empty array item on mount, how can I avoid that and conditionally render a <p>
tag that tells the user there's no items in the array yet? I have tried this code but it didn't work. This is my component (I know I have to refactor it, I just want to make it work first):
import React, { useState, useEffect } from "react"
const formatThousands = require("format-thousands")
const Clients = () => {
const [client, setClient] = useState({})
const [allClients, setAllClients] = useState([])
const [name, setName] = useState("")
const [cuota, setCuota] = useState("")
const [id, setId] = useState("")
useEffect(() => {
setAllClients([...allClients, client])
}, [client])
function handleSubmit(event) {
event.preventDefault()
if (!name || !cuota || !id) return
setClient({ ...client, name, cuota, id })
setName("")
setCuota("")
setId("")
}
function handleDeleteButton(id) {
allClients.filter(cl => id !== cl.id)
}
return (
<div className="container">
<form className="input-group" onSubmit={handleSubmit}>
<span className="input-group-text">Nuevo cliente</span>
<input
type="text"
className="form-control"
placeholder="Agregar un nuevo cliente"
value={name}
onChange={event => setName(event.target.value)}
/>
<input
type="number"
placeholder="Monto cuota"
className="form-control"
value={cuota}
onChange={event => setCuota(event.target.value)}
/>
<input
type="number"
placeholder="identificador"
className="form-control"
value={id}
onChange={event => setId(event.target.value)}
/>
<button className="btn btn-success" type="submit">
Agregar
</button>
</form>
<div className="text-center my-2">
<h3>Clientes</h3>
</div>
<table className="table table-striped">
<thead>
<tr>
<th scope="col">Cliente</th>
<th scope="col">Cuota</th>
<th scope="col">Identificador</th>
</tr>
</thead>
<tbody>
{allClients ? (
allClients.map(client => (
<tr key={client.id}>
<td>{client.name}</td>
<td>{formatThousands(client.cuota)}</td>
<td>{client.id}</td>
<td>
<button
onClick={() => handleDeleteButton(client.id)}
className="btn btn-danger btn-sm"
>
Borrar
</button>
</td>
</tr>
))
) : (
<p>Sin clientes</p>
)}
</tbody>
</table>
</div>
)
}
export default Clients
This is the output I get on mount:
This is the initial value of allClients, I don't know why Array [ {} ]
This is your current code:
allClients ? allClients.map : <p></p>
In contrast, this is what your code should be:
allClients.length ? allClients.map : <p></p>
allClients is an empty array so it returns true. Instead, your code should check allClients.length which actually returns the length of the array.
This is caused by the useEffect
block. You add and empty object to the array the first time the component is rendered. That is why this condition allClients.length > 0
is true:
This is the initial value of allClients, I don't know why Array [ {} ]
Solution 1: Initialize allClients
with null
. Do the same with client. Check if client has value:
const [client, setClient] = useState(null)
const [allClients, setAllClients] = useState(null);
useEffect(() => {
if(client) setAllClients([...allClients || [], client]);
}, [client]);
Solution 2: Initialize only client with null and then check for allClients.length > 0 to render the elements.
const [client, setClient] = useState(null)
const [allClients, setAllClients] = useState([]);
useEffect(() => {
if(client) setAllClients([...allClients, client]);
}, [client]);
In both case you will need to check if client has a valid value.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.