Im tryng to repeat react element for certain amount of times. I have used for loop before and it was working with simple HTML elements. Now it wont work, constantly getting error that 'fields' array is undefined. Here is my code:
import { useRef, useState } from 'react';
import SecondForm from './SecondForm';
function App() {
const inputRef = useRef(null);
[fields, setFields] = useState([]);
const setFields = () => {
let numberOfAngles = inputRef.current.value;
for (let i = 1; i <= numberOfAngles; i ) {
fields.push(<SecondForm id={i} key={i}></SecondForm>);
}
};
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"
ref={inputRef}
></input>
<button className="btn" onClick={setFields}>
Sumbit
</button>
</div>
{fields ? fields : null}
</div>
);
}
I also have tried with .map but still getting same error... Any help is welcome.
CodePudding user response:
You const setFields
overrides the setFields
from [fields, setFields] = useState([]);
, and you need to use that to inform react that the array has changed and that it should re-render.
so the fixed code for this approach would be
const inputRef = useRef(null);
const [fields, setFields] = useState([]);
const setFieldsHandler = () => {
let numberOfAngles = inputRef.current.value;
const newFields = []
for (let i = 1; i <= numberOfAngles; i ) {
newFields.push(<SecondForm id={i} key={i}></SecondForm>);
}
setFields(newFields);
};
but there really is no reason to hold the whole react components in a state. Just keep the count in the state and use it to render them directly.
import { useRef, useState } from "react";
import SecondForm from "./SecondForm";
function App() {
const inputRef = useRef(null);
const [fieldsCount, setFieldsCount] = useState(0);
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"
ref={inputRef}
></input>
<button
className="btn"
onClick={(e) => setFieldsCount(inputRef.current.value)}
>
Sumbit
</button>
</div>
{Array(fieldsCount)
.fill()
.map((_, index) => (
<SecondForm id={index} key={index}></SecondForm>
))}
</div>
);
}
CodePudding user response:
Setting directly the fields array is not the right way to change the state using useState hook. Instead you should change it using the setFields function. To add a value to the fields array first spread the previous state, by passing setFields a function, and add the new item to the array.
setFields((prevState) => [...prevState, newItem]);
CodePudding user response:
i test this code in sandbox and work fine you can use it
import { useRef, useState } from "react";
function App() {
const inputRef = useRef(null);
const [fields, setFields] = useState("");
const setField = () => {
let numberOfAngles = inputRef.current.value;
for (let i = 1; i <= numberOfAngles; i ) {
setFields(<p>Hi!</p>);
}
};
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"
ref={inputRef}
></input>
<button className="btn" onClick={setField}>
Sumbit
</button>
</div>
{fields ? fields : null}
</div>
);
}
export default App;