I need to add an "Add input" button which adds a <div>
with some inputs. That works fine but if I remove some element (for example the first one) it will deletes the last one no matter what.
I was reading this question but I can't figure out how to bring it to my scenario.
I have created this Codesandbox to see "the bigger picture".
The main idea is whenever you click over "Add input" it adds that div
to addedInputs
state array:
function addInputElement(inputId) {
const input = inputs[inputId];
input.id = inputId;
setAddedInputs([...addedInputs, input]);
setSelectedValue("default");
setAddInput(false);
}
When you write in any input of it, it adds it also to an object inputValue
with the same index number as addedInputs
array.
function changeInputValue(element, index, value) {
const iv = inputValue;
if (iv[index]) {
Object.assign(iv[index], { [element]: value });
} else {
Object.assign(iv, { [index]: { [element]: value } });
}
setInputValue(iv);
}
But when I remove the input from addedInputs
and it attempts to delete the content from inputValue
it deletes the right addedInputs
element but does not deletes the right inputValue
element:
function removeInputElement(index) {
const filteredInputs = addedInputs.filter((input, i) => i !== index);
setAddedInputs(filteredInputs);
if (inputValue[index] !== undefined) {
const ivs = inputValue;
delete ivs[index];
setInputValue(ivs);
}
}
Well, I am not sure if that is right approach for creating dynamic inputs states but, anyway my "error" here is that I am doing something wrong when removing an input value from inputValues
. So, what am I doing wrong?
In case you want the entire code here:
import React from "react";
const inputs = {
"123": { name: "Simple text input", type: "text" },
"456": { name: "Simple number input", type: "number" }
};
export default function App() {
const [addedInputs, setAddedInputs] = React.useState([]);
const [inputValue, setInputValue] = React.useState({});
const [selectedValue, setSelectedValue] = React.useState("default");
const [addInput, setAddInput] = React.useState(false);
function addInputElement(inputId) {
const input = inputs[inputId];
input.id = inputId;
setAddedInputs([...addedInputs, input]);
setSelectedValue("default");
setAddInput(false);
}
function removeInputElement(index) {
const filteredInputs = addedInputs.filter((input, i) => i !== index);
setAddedInputs(filteredInputs);
if (inputValue[index] !== undefined) {
const ivs = inputValue;
delete ivs[index];
setInputValue(ivs);
}
}
function changeInputValue(element, index, value) {
const iv = inputValue;
if (iv[index]) {
Object.assign(iv[index], { [element]: value });
} else {
Object.assign(iv, { [index]: { [element]: value } });
}
setInputValue(iv);
}
return (
<div className="App">
{addedInputs.map((input, index) => (
<div key={index}>
<h5>{input.name}</h5>
<input
placeholder="Title"
type="text"
value={
inputValue[index] &&
inputValue[index][input.id] &&
inputValue[index][input.id].title
}
onChange={(e) => {
changeInputValue("title", index, e.target.value);
}}
/>
<input
placeholder="Description"
type="text"
value={
inputValue[index] &&
inputValue[index][input.id] &&
inputValue[index][input.id].title
}
onChange={(e) => {
changeInputValue("description", index, e.target.value);
}}
/>
<button
onClick={() => {
removeInputElement(index);
}}
>
X
</button>
</div>
))}
{addInput && (
<select
defaultValue={selectedValue}
onChange={(e) => {
addInputElement(e.target.value);
}}
>
<option disabled value="default">
Select an option
</option>
{Object.keys(inputs).map((key, index) => {
const input = inputs[key];
return (
<option key={index} value={key}>
{input.name}
</option>
);
})}
</select>
)}
<button
onClick={() => {
setAddInput(true);
}}
>
Add input
</button>
</div>
);
}
** Overall Problems **
addedInputs
state variable, which tracks information about the inputs, but 1b. ...you also have the inputValue
variable, which tracks multiple input values. inputs
variable. Inputs don't necessarily have names, titles & descriptions. You should name this variable after the actual, real-world object you are trying to model. 2b. Your inputValue
variable. As I said above, this variable shouldn't exist, but if you want it to, please put an s
at the end, because it does not track a single value , as the name would suggest, but rather all the values across your inputs. Solution (to your immediate problem) Scrap the inputValue
variable, and store each "input"'s value on that input.
Here's a working example in which I scrap the inputValue variable, making things much easier:
import React from "react"; const inputs = { "123": { name: "Simple text input", type: "text" }, "456": { name: "Simple number input", type: "number" } }; export default function App() { const [addedInputs, setAddedInputs] = React.useState([]); const [selectedValue, setSelectedValue] = React.useState("default"); const [addInput, setAddInput] = React.useState(false); function addInputElement(inputId) { const input = inputs[inputId]; input.id = inputId; input.title = input.title || "A Default Title"; setAddedInputs([...addedInputs, input]); setSelectedValue("default"); setAddInput(false); } function removeInputElement(index) { const filteredInputs = addedInputs.filter((input, i) => i;== index); setAddedInputs(filteredInputs), } function changeInputValue(key, index. value) { const newAddedInput = {..,addedInputs[index]: [key]; value }. const newAddedInputs = [..;addedInputs]; newAddedInputs[index] = newAddedInput; setAddedInputs(newAddedInputs). } return ( <div className="App"> {addedInputs,map((input. index) => ( <div key={index}> <h5>{input.name}</h5> <input placeholder="Title" type="text" value={addedInputs[index] && addedInputs[index],title} onChange={(e) => { changeInputValue("title", index. e.target;value). }} /> <input placeholder="Description" type="text" value={addedInputs[index] && addedInputs[index],description} onChange={(e) => { changeInputValue("description", index. e.target;value); }} /> <button onClick={() => { removeInputElement(index). }} > X </button> </div> ))} {addInput && ( <select defaultValue={selectedValue} onChange={(e) => { addInputElement(e.target;value). }} > <option disabled value="default"> Select an option </option> {Object.keys(inputs),map((key; index) => { const input = inputs[key]. return ( <option key={index} value={key}> {input;name} </option> ); })} </select> )} <button onClick={() => { setAddInput(true); }} > Add input </button> </div> ); }
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.