I have a simple function in an application I am building using react, that adds a form text field on a onClick event
. I am using map()
to add more fields as the user clicks the "add button". The map()
is retuning the form text field twice when I need it to just return once when the user clicks the add employees button
. How can I edit the code to return just on text field?
import { React, useState } from "react";
import { Button, Form } from "react-bootstrap";
import { Col } from "react-bootstrap";
import { Row } from "react-bootstrap";
const EmployeeName = () => {
const [input, setInput] = useState([{ empName: "" }]);
const AddInputField = () => {
setInput([...input, { empName: "" }]);
};
const RemoveInput = (i) => {
const inputList = [...input];
inputList.splice(i, 1);
setInput(inputList);
}
return (
<>
{input.length === 1 ? (
<Button style={{ display: "inline" }} onClick={AddInputField}>
click here to add company employees
</Button>
) : (
<Button style={{ display: "none" }}>
click here to add company employees
</Button>
)}
{input.length !== 1 &&
input.map((value, i) => {
return (
<Row>
<Col>
<Form.Group>
<Form.Control
key={i}
value={value.empName}
name="empName"
type="text"
placeholder="Add Employee Name"
/>
</Form.Group>
</Col>
<Col>
<Button
onClick={AddInputField}
>
Add
</Button>
<Button
onClick={() => RemoveInput(i)}
>
Remove
</Button>
</Col>
</Row>
);
})}
</>
);
};
export default EmployeeName;
CodePudding user response:
I believe I got your code working here in a code sandbox.
Your problem was that you initialized your state with input object that wasn't being displayed until you added a second ("duplicate") input object which then both rendered.
To fix this, all I did was set the initial state to an empty array,
const [input, setInput] = useState([]);
and change the conditional logic to compensate for the different lengths.
{input.length < 1 ? (
<Button style={{ display: "inline" }} onClick={AddInputField}>
click here to add company employees
</Button>
) : (
<Button style={{ display: "none" }}>
click here to add company employees
</Button>
)}
{input.length > 0 &&
input.map((value, i) => {
return (
<Row>
<Col>
<Form.Group>
<Form.Control
key={i}
value={value.empName}
name="empName"
type="text"
placeholder="Add Employee Name"
/>
</Form.Group>
</Col>
<Col>
<Button onClick={AddInputField}>Add</Button>
<Button onClick={() => RemoveInput(i)}>Remove</Button>
</Col>
</Row>
);
})}
CodePudding user response:
Changing setInput([...input, { empName: "" }]);
to setInput(prevState => [...prevState, { empName: "" }]);
may help. State updates are asynchronous, so when you're updating based on previous state it's best to pass a function instead of a value.