1

Scenario:
You have an input field on a page, and whatever number user puts in, I want to generate that much more inputs. Each input generated represents values that user can choose. By default, we generate values from 0 -> N.

Example: if user sets input to 5 we would generate 5 inputs, each having values from 0 -> 4

Problem:
The values we generate by default might change. For example, user maybe wants to change one of the inputs to his value.

Example: Users sets 5, we generate 5 inputs, from 0 -> 4, then he decides that we wants to change one of the values to 42. In that case, we would have, for example:

input1: 0
input2: 1
input3: 3
input4: 42

Question
I want/need to have this values in state because otherwise I can not update the value as they type into the inputs.

The problem I am facing is: how can I know which one he is typing into? The inputs are generated dynamically.

If I set inputs to have a inputChangeHandler() what to check inside that function to know which state value to change? Also, since other values need to be preserved, I only need to change that key, not others.. Lots of issues I am facing as you see. :) Any advice would be appreciated.

Demo
Editor: https://stackblitz.com/edit/react-gaq7eh
Live: https://react-gaq7eh.stackblitz.io (input is in the top left corner)

P.S - not sure if editor changes reflect everywhere, so just in case, here's the code:

import React, { Component } from 'react';
import { render } from 'react-dom';
import Hello from './Hello';
import './style.css';

class InputProblem extends React.Component {
  constructor() {
    super();
    this.state = {
      inputs: [],
      inputValue: null
    };
  }

  generateInputs = (value) => {
    this.setState({inputs: Array.from(Array(Number(value)).keys()), inputValue: Number(value)})
  }

  render() {
    return (
      <div>
      <input className="main-input" type="text" value={this.state.inputValue} onChange={(e) => this.generateInputs(e.target.value)} />
      {
        this.state.inputs.map(item => (
          <input type="text" value={item}/>
        ))
      }
      </div>

    )
  }
}
render(<InputProblem />, document.getElementById('root'));

2 Answers 2

1

One option without changing too much code is figuring out which input it is by keeping track of index in an onChange handler for each respective input

handleInputTextUpdate = (idx) = (e) => {
  const nextInputState = [...this.state.inputs]
  nextInputState[idx] = e.target.value
  this.setState({inputs: nextInputState})
}
this.state.inputs.map((item, index) => (
  <input onChange={this.handleInputTextUpdate(index)} />
)
Sign up to request clarification or add additional context in comments.

2 Comments

Both answers provided some insight, but I managed to get it working using your suggestion. I actually thought about doing this but decided it was a "dirty" solution (copying state to another object then setting it back). Unfortunately, I found no other elegant solutions. Thank you for your help, Andrew!
There are more elegant methods of handling this, but I prefaced it with low code changes ;). If you want a better solution, make this.state.inputs an object, where the key is a unique id. It's essentially the same process, only you would be more declarative with a distinct id, instead of an index number
1

You can add an unique id to each input, and then you can use this id to figure out which input is changing.

 this.state.inputs.map((item, index) => (
        <input type="text" key={index} id={index} value={item} 
        onChange={(e) => {  console.log("e.target.id: "+ e.target.id + " value: " + e.target.value)}} />
        ))

Access element's id with e.target.id.

3 Comments

if I set value={item} then it can not be changed. I have to set it to something like {this.state.my_custom_key} which I haven't set yet. Any suggestion on how/where to do that?
@py9 I would use an array. Like this: yourArray[e.target.id] = e.target.value
I decided to go with Andrew's solution as I managed to get it working with that technique first :) Nevertheless, thank you for your time and solution. Definitely pushed me into right direction.

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.