Home > Software design >  React is constantly giving undefined variable error
React is constantly giving undefined variable error

Time:11-11

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;

  • Related