Fetching the input value from textarea in a loop from an array of objects using reactjs. How to do so?

I managed to display X amount of text areas based on the JSON object data I received. I'm wondering how would i obtain A SINGLE user input when they input something in the textarea. I manage to input and get the textarea value but all the textarea values seem to change to the value I enter. How would I enter and obtain ONE SINGLE value and only display what the user inputs for that index only?

DISPLAYING THE TEXTAREAS BASED ON THE DATABASE VALUES, however the input values are not editable or savable by my button

const WorkInProgressHLEDevDays = () =>{
  return (
    <tr>
    <th> TEXTAREAs </th>
    {this.state.WIPHLEsData.map((HLEDevDayTextAreas, i) => (
        <td key={i}>
        <textarea className="HLEDevDays" onChange={this.handleChange} value={HLEDevDayTextAreas.HLEDevDays} spellcheck="false">

        </textarea>
        </td>
    ))}

    </tr>

  )
}

LINK TO HOW IT LOOKS WHEN USER TYPES SOMETHING IN THE TEXTAREA

1 answer

  • answered 2018-10-11 20:57 joehdodd

    The issue you're having is that, for every one of the <textarea> JSX elements you return from your map() method, they're all reading the same value off of state beacause they all use the same key.

    Here's the snippet where that's happening.

    value ={this.state.jiraWIPHLEsHLEDevDays}

    Hence, as you type in any of the text areas, they all render the same text because that's how they're set up. Since you're generating the text areas from a map() method, the text areas themselves will be unique with keys, but you're supplying each of them all with the same key for their input value in state.

    What you'll need to do is dynamically create and update the value for each textarea. React has a method for doing this by supplying each input with a name attribute. This will allow you to target that unique value (e.target.name) in your handleChange method.

    But, again, since you're creating the text areas dynamically, you'll also have to dynamically create a unique value attribute for each. You can do this pretty easily just by using string interpolation to create a unique value attribute as you return the text areas from the map() method.

    As I've done below, ensure that the values of the name and value attributes match, because handleChange() will set the name attribute to component state as you type, and in turn your text area will expect to be able read a value of the same key off of state.

    Check out and run the snippet I've supplied below for the details of everything, and to test the implementation.

    class RenderTextAreas extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          issues: {
            iOne: 'an issue',
            iTwo: 'another issue',
            iThree: 'yet another issue'
          }
        };
      }
      handleChange = e => {
        let value = e.target.value;
        // create a variable called "name" and store the name attribute in it
        // this variable's value will be unique for each text area
        let name = e.target.name;
        // set that to state, along with the input value
        this.setState({ name: e.target.value });
      };
      render() {
        return (
          <div>
            {Object.keys(this.state.issues).map((issue, i) => (
              <textarea
                key={i}
                placeholder={`${issue}_value`}
                // supply a unique "name" attribute using string interpolation 
                name={`${issue}_value`}
                // read each unique value by using a combination of
                // bracket notation and string interpolation that matches
                // the name attribute above
                value={this.state[`${issue}_value`]}
                onChange={this.handleChange}
              />
            ))}
          </div>
        );
      }
    }
    
    ReactDOM.render(<RenderTextAreas />, document.getElementById('app'));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
    <div id="app"></div>

    I hope that this helps solve your problem! Let us know.