Home > database >  Hande input onChange event in dynamic react js form
Hande input onChange event in dynamic react js form

Time:06-17

I have a Form component with a title input and a dynamic number of ingredient inputs (the user can add and remove them with corresponding buttons). Most of the form functions properly. However, I receive a warning that I have passed a value prop to a form field without an onChange handler for the ingredient input element(s).

In render() for my Form component, this part should dynamically generate inputs (EDIT: by mapping from an array of ingredients in my Form's state):

{this.state.ingredients.map((element, i) => {
                    return (
                        <div key={i}>
                            <input
                                type='text'
                                placeholder='new ingredient'
                                value={element || ''}
                                onChange={this.handleIngredientChange.bind(this)}
                            />
                        </div>
                    );
                })}

I thought these inputs would connect to my handleIngredientChange method to update the state of the ith ingredient name when the user changes the input value:

    handleIngredientChange(i, event) {
        let ingredients = [...this.state.ingredients];
        ingredients[i] = event.target.value;
        this.setState({ingredients});
    }

And that this method would appropriately allow react to control each input element.

I seem to be misunderstanding this and/or .bind(), because I clearly assigned onChange={this.handleIngredientChange.bind(this)} to the ingredient input element in my map function. When the user types in one of these inputs, we get `TypeError: undefined is not an object (evaluating 'event.target').

Perhaps the root of the problem is that when the user types in the input, handleIngredientChange is not correctly set up to get the user's desired input value, but I cannot see where the error is.

I have looked at a lot of similar questions and have tried to implement their answers to no avail. Could anyone point me in the right direction on why I have not handled the onChange event properly? I'd be more than happy to explain my intentions further if you need me to. Many thanks in advance.

Full code:

export default class Form extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            title: '',
            ingredients: [],
        };
    }

    handleTitleChange(event) {
        let title = this.state.title;
        title = event.target.value;
        this.setState({title});
    }

    handleIngredientChange(i, event) {
        let ingredients = [...this.state.ingredients];
        ingredients[i] = event.target.value;
        this.setState({ingredients});
    }

    removeClick(i) {
        let ingredients = [...this.state.ingredients];
        ingredients.splice(i, 1);
        this.setState({ingredients});
    }

    addClick() {
        let ingredients = [...this.state.ingredients];
        ingredients.push('');
        this.setState({ingredients});
    }

    handleSubmit(event) {
        console.log('submit request logged')
        event.preventDefault();
    }

    render() {

        return (
            <form onSubmit={this.handleSubmit}>
                <input
                    type='text'
                    placeholder='recipe title'
                    value={this.state.title || ''}
                    onChange={this.handleTitleChange.bind(this)}
                />
                {this.state.ingredients.map((element, i) => {
                    return (
                        <div key={i}>
                            <input
                                type='text'
                                placeholder='new ingredient'
                                value={element || ''}
                                onChange={this.handleIngredientChange.bind(this)}
                            />
                        </div>
                    );
                })}
                <input
                    type='button'
                    value='add'
                    onClick={this.addClick.bind(this)}
                />
                <input
                    type='Submit'
                    value='save'
                    onClick={this.handleSubmit.bind(this)}
                />
            </form>
        )
    }
}

CodePudding user response:

I'm not sure if this helps

try change

<input
                type="text"
                placeholder="new ingredient"
                value={element || ""}
                id={i}
                onChange={this.handleIngredientChange.bind(this)}
              />

and then alter

 handleIngredientChange(event) {
    let ingredients = [...this.state.ingredients];
    ingredients[event.target.id] = event.target.value;
    this.setState({ ingredients });
  }

https://codesandbox.io/s/react-playground-forked-yf7rpm

  • Related