I am trying to figure out how to submit an arbitrary amount of array elements, so at least one to infinity.
This is a state that gets passed at the click of a submit button:
const [gallery, setGallery] = useState({
title: "",
description: "",
image_url: [],
});
I am looping the following state...
const [linkInput, setLinkInput] = useState([{ id: 1, link: "" }]);
...like so:
<div className="form-group mx-sm-3 mb-2">
<label htmlFor="image_url">Image URLs*</label>
{Array.isArray(linkInput) &&
linkInput.map((input, i) => (
<div className="input-group mb-3" key={input.id}>
<input
className="form-control"
id="image_url"
type="text"
value={input.link}
required
onChange={(e) =>
onChangeLink({ ...input, link: e.target.value })
}
/>
<br />
<div style={{ color: "#ffffff" }}>__</div>
{linkInput.length !== 1 && (
<>
<button
type="button"
className="btn btn-primary"
onClick={() => removeLink(input.id)}
>
Remove Image
</button>
</>
)}
</div>
))}
<br />
<button
type="button"
className="btn btn-primary"
onClick={() => addInput()}
>
Add another image
</button>
</div>
These are functions I am using to add or remove input fields by modifying the "linkInput" state:
const handleRemoveLink = (id) => {
setLinkInput(linkInput.filter((el) => el.id !== id));
};
const handleAddInputField = () => {
const lastItem = linkInput[linkInput.length - 1];
setLinkInput([...linkInput, { id: Number(lastItem.id 1), link: "" }]);
};
I am trying to take the "link" value from each input element and place it in "image_url: []" upon clicking on submit button on my form. Currently I am not even close, the form behaves as such: it totally disappears when placing even a single character. What should I do?
CodePudding user response:
You can do it by mapping over the existing linkInput
array with map
which returns a new array.
const handleLink = (e, index) => {
const result = linkInput.map((linkObj, i) => {
if (i === index) {
// create a new object with the values of the previous link object
// set the link prop to the new value
return {
...linkObj,
link: e.target.value,
};
}
return linkObj;
});
setLinkInput(result);
};
A common mistake is to not return a new object and mutate the linkObj
directly. When doing so you'll change the original object.
const linkInput = [{ id: 1, link: "" }];
let result = [...linkInput];
result = result.map((x, i) => {
if (i === 0) x.link = "mutated";
return x;
});
console.log('linkInput',linkInput);
console.log('result',result);
As you can see both of the array's have the "mutated" value while did copy the list.
CodePudding user response:
The solution was to specify exactly what event corresponds to what array element:
const handleLink = (e, index) => {
let result = [...linkInput];
result = result.map((x, i) => {
if (i === index) x.link = e.target.value;
return x;
});
setLinkInput(result);
};
NOTE: I dropped "id" property on linkInput in favor of indexes.