1

I have a number, n, that can be any value and I want to render n input fields while keeping track of each input's state but I'm having trouble figuring out how. For example, if n = 3, I want to render something like this:

<div>
    <input onChange={(e) => setValue1(e.target.value)}/>
    <input onChange={(e) => setValue2(e.target.value)}/>
    <input onChange={(e) => setValue3(e.target.value)}/>
< /div>

In this example, I would manually need to create three states: value1, value2, value3. My goal is to have it dynamic so if in the future I change n to 4 or any other number, I don't have to manually create more states and mess with the component. Is there a good way to accomplish this using hooks?

0

5 Answers 5

1

You have to create a inputs state in order to track every input:

import React, { useState } from 'react';
import './style.css';

export default function App() {
  const [inputs, setInputs] = useState(Array(10).fill(''));
  const inputChangedHandler = (e, index) => {
    const inputsUpdated = inputs.map((input, i) => {
      if (i === index) {
        return e.target.value;
      } else {
        return input;
      }
    });
    setInputs(inputsUpdated);
  };
  return (
    <div>
      {inputs.map((input, i) => (
        <input onChange={e => inputChangedHandler(e, i)} value={input} />
      ))}
    </div>
  );
}

You can check here, how things work: https://stackblitz.com/edit/react-sdzoqh

Sign up to request clarification or add additional context in comments.

Comments

0

You can create a new array with useState hook of size num that is passed from its parent and then using its index i.e. i you can change its input value using setValue function.

CODESANDBOX DEMO

Just for DEMO purpose and make the input come to a new line so I've wrapped it into div.

export default function App({ num }) {
  const [arr, setValue] = useState(Array(num).fill(""));
  console.log(arr);

  function onInputChange(index, event) {
    console.log(event.target.value);
    setValue((os) => {
      const temp = [...os];
      temp[index] = event.target.value;
      return temp;
    });
  }

  return (
    <div className="App">
      {arr.map((n, i) => {
        return (
          <div key={i}>
            <input onChange={(e) => onInputChange(i, e)} value={n} />
          </div>
        );
      })}
    </div>
  );
}

Comments

0

Maybe I would create a custom hook to generate my inputs like

import React, { useState } from "react";

const CreateInput = (n) => {
    const array = new Array(n).fill("");
    const [valueInput, setValueInput] = useState({});

    const handleChange = (event) => {
        const { name, value } = event.target;

        setValueInput({
            ...valueInput,
            [name]: value,
        });
    };

    const Input = array.map((_, i) => (
        <input key={i} name={i} onChange={handleChange} />
    ));

    return {
        Input,
    };
};

const Inputs = () => {
    const { Input } = CreateInput(3);

    console.log(Input);

    return <div>{Input}</div>;
};

export default Inputs;

Comments

0

This could be done with an array in the state, with the values in the inputs. Initialize with empty strings

const [values, setValues] = useState(Array(n).fill(""))
const handleChange = (e, i) => {
    const copy = values;
    copy[i] = e.target.value
    setValues(copy)
}
return (
    <div>
        {Array(n).map((x,i) => (
            <input value={values[i]} onChange={e => handleChange(e,i)} />
))}
    </div>
)

Comments

0

you can use useState([]) with array as default value for example

import "./styles.css"; import React, { useState } from "react";

export default function App() {
  const n = 3;
  const [values, setValues] = useState(new Array(n).fill(1, 0, n));

  const handleChange = (i, value) => {
    const v = [...values];
    v[i] = value;
    setValues(v);
    
  };

  const inputsRendrer = (values) => {
    return values.map((v, i) => {
      return (
        <input
          key={i}
          value={values[i]}
          onChange={(event) => handleChange(i, event.target.value)}
        />
      );
    });
  };
  return <div className="App">{inputsRendrer(values)}</div>;

}

new Array(n).fill(1, 0, n) // this create new array with values of 1 and length of n`

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.