Notorious776
Notorious776

Reputation: 493

How can I create an array of states in React using hooks?

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?

Upvotes: 1

Views: 976

Answers (5)

YAGOUBI A.E.K
YAGOUBI A.E.K

Reputation: 111

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`

Upvotes: 0

Daniel M
Daniel M

Reputation: 143

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>
)

Upvotes: 0

Daphaz
Daphaz

Reputation: 506

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;

Upvotes: 0

Soufiane Boutahlil
Soufiane Boutahlil

Reputation: 2604

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

Upvotes: 1

DecPK
DecPK

Reputation: 25398

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>
  );
}

Upvotes: 0

Related Questions