Search code examples
javascriptreactjssetstate

React: Setting state to an array based on textarea input


I am trying to set the state of features, which is an array, based on inputs into textarea. I am having no luck setting the state of features. When I press one key, that key becomes the next index value in the state. If I hit another key, that key becomes the next index value in the state. So if I manually set my initial state of features to features: ["First", "Second", "Third"],, the result will be features: ["First", "Second", "Third", "Firstf" , "Firstd"] if I hit f and then d

The relevant State

class CreateItem extends Component {
  state = {
    features: [""],
  };

This is how I am attempting to create textarea's based on the state

                <label htmlFor="features">
                  Features
                  {this.state.features.map((feature, i) => (
                    <div key={i}>
                      <textarea
                        key={i}
                        type="features"
                        placeholder={`${feature}`}
                        name={`features.${i}`}
                        value={this.state.features[`${i}`]}
                        onChange={this.handleFeatureArrayChange}
                        onKeyDown={this.keyPress}
                      />
                    </div>
                  ))}
                </label>

Here is the handleChange

  handleFeatureArrayChange = e => {
    const { name, type, value } = e.target;
    this.setState(prevState => ({
      [name]: [...prevState.features, value]
    }));
  };

This is how I am attempting to create new textarea's each time the user hits enter:

  keyPress = e => {
    if (e.keyCode == 13) {
      this.setState({
        features: this.state.features.concat("")
      });
    }
  };

Solution

  • The problem is you're just appending to state each time a key is pressed.

      handleFeatureArrayChange = e => {
        const { name, type, value } = e.target;
        this.setState(prevState => ({
          [name]: [...prevState.features, value] // this is effectively the same as .concat(value)
        }));
      };
    

    You want to update the value at the current index. Try changing the name of the input to just be key and then mapping instead

      handleFeatureArrayChange = e => {
        const { name, type, value } = e.target;
        this.setState(prevState => ({
          features: prevState.features.map((feat, key) => {
            if (key == name) {
              return value
            } else
              return feat;
            }
          )
        }));
      };