I am trying to map one react element for n times. Element consist two input fields: x and y.
I have managed to do this, but when I enter some value in x field, all x fields on all Element are getting that value.
Second part of problem is when I try to take values of input fields into array of objects (eg. [{x:10, y:20},{x:30, y:70},{x:100, y:5}]), there is error that "Map is not a function."
Here is code and CodePen link: https://codesandbox.io/s/vigilant-shape-d250yz?file=/src/App.js
import "./styles.css";
import { useRef, useState } from "react";
import SecondForm from "./SecondForm";
function App() {
const inputRef = useRef(null);
const [fieldsCount, setFieldsCount] = useState(0);
const [xPolygonInput, setXInput] = useState(0);
const [yPolygonInput, setYInput] = useState(0);
let secondForm = document.getElementsByClassName("second-form");
console.log(secondForm);
let items = [];
let createArrayOfObjects = () => {
console.log(xPolygonInput, yPolygonInput);
items.push(
secondForm.map(() => {
return {
x: { xPolygonInput },
y: { yPolygonInput }
};
})
);
console.log(items);
};
return (
<div className="app">
<h1>Check is point inide of polygon or not</h1>
<div className="start-form">
<p>Select number from 3 to 10 for number of Polygon angles</p>
<input
type="number"
id="nr-of-angles"
name="nr-ofangles"
min="3"
max="10"
required
ref={inputRef}
></input>
<button
className="btn"
onClick={() => setFieldsCount(inputRef.current.value)}
>
Submit
</button>
</div>
<div className="coordinates">
<div className="coordinates-wrap">
<div className="angle-wrapper">
<p>Angle Coordinates</p>
<div className="angle-inner">
{Array(parseInt(fieldsCount))
.fill()
.map((i, index) => (
<SecondForm
id={index}
key={index}
xPolygonInput={xPolygonInput}
yPolygonInput={yPolygonInput}
setXInput={setXInput}
setYInput={setYInput}
className="second-form"
>
<p>Group {index + 1}</p>
</SecondForm>
))}
</div>
<br />
<button onClick={createArrayOfObjects} className="btn">
Create Array of Objects
</button>
</div>
</div>
</div>
</div>
);
}
export default App;
Replacing react element with simple html code did not helped. First part of problem (repeating input on all x or y fields) may have some connection with .fill(), but if I remove it map does not work... Any help is welcomed! :)
I would suggest storing the entire positions (x, y) as an array of objects.
Callback would then update the correct position based on index (or ID if applicable).
You can take a look at the example code below.
SecondForm.jsx
function SecondForm({ x, y, onXChange, onYChange }) {
// const [input, setInput] = useState(props?.value ?? '');
return (
<div className="angle-input">
<form>
{/* <label>Enter X and Y coordinates for Polygon angles</label> */}
<div className="angle-coordinates">
<p>Angle</p>
<input
type="number"
min="0"
max="500"
placeholder="x"
className="xPolygon"
name="nr-ofangles"
value={x}
onChange={onXChange}
required
></input>
<input
type="number"
min="0"
max="400"
placeholder="y"
className="yPolygon"
name="nr-ofangles"
value={y}
onChange={onYChange}
required
></input>
</div>
</form>
</div>
);
}
export default SecondForm;
App.jsx
import "./styles.css";
import { useRef, useState } from "react";
import SecondForm from "./SecondForm";
function App() {
const inputRef = useRef(null);
const [positions, setPositions] = useState([]);
const handleCreatePositions = () => {
const pos = Array.from(
{ length: parseInt(inputRef.current.value, 10) },
() => ({ x: 0, y: 0 })
);
setPositions(pos);
};
const handleOnInputChange = (e, index, axis) => {
setPositions((prevPositions) => {
const newPositions = [...prevPositions];
newPositions[index] = {
...newPositions[index],
[axis]: e.target.value
};
return newPositions;
});
};
return (
<div className="app">
<h1>Check is point inide of polygon or not</h1>
<div className="start-form">
<p>Select number from 3 to 10 for number of Polygon angles</p>
<input
type="number"
id="nr-of-angles"
name="nr-ofangles"
min="3"
max="10"
required
ref={inputRef}
></input>
<button className="btn" onClick={handleCreatePositions}>
Submit
</button>
</div>
<div className="coordinates">
<div className="coordinates-wrap">
<div className="angle-wrapper">
<p>Angle Coordinates</p>
<div className="angle-inner">
{positions.map((position, index) => (
<SecondForm
id={index}
key={index}
x={position.x}
y={position.y}
onXChange={(e) => handleOnInputChange(e, index, "x")}
onYChange={(e) => handleOnInputChange(e, index, "y")}
className="second-form"
>
<p>Group {index + 1}</p>
</SecondForm>
))}
</div>
<br />
<button onClick={() => console.log(positions)} className="btn">
Create Array of Objects
</button>
</div>
</div>
</div>
</div>
);
}
export default App;