Search code examples
javascriptreactjstypescriptmaterial-uireact-dom

How to Pass Key value from inputText change in ReactJs in typescript?


I am using switch case for comparison for object key with string in below code:

import { TextField, Button } from "@material-ui/core";
import React, { Component, ReactNode } from "react";

import classes from "./Contact.module.scss";

class contactForm extends Component {
    state = {
        contactForm: {
            name: "",
            email: "",
            message: "",
            phone: ""
        }
    };

    render(): ReactNode {
        return (
            <form className={classes.ArticleBody}>
                <div className={classes.ContactForm}>
                    <TextField
                        value={this.state.contactForm.name}
                        onChange={event => this._inputChangeHandler(event, "name")}
                        label="Full Name"
                        required
                    />
                    <TextField
                        value={this.state.contactForm.email}
                        onChange={event => this._inputChangeHandler(event, "email")}
                        type="Email"
                        label="Email"
                        required
                    />
                    <TextField
                        value={this.state.contactForm.phone}
                        onChange={event => this._inputChangeHandler(event, "phone")}
                        type="phone"
                        label="Phone Number"
                        required
                    />
                    <TextField
                        type="textarea"
                        value={this.state.contactForm.message}
                        label="Comment/Message"
                        rows="4"
                        onChange={event => this._inputChangeHandler(event, "message")}
                        multiline
                        required
                    />
                </div>

                <div className={classes.Submit}>
                    <Button type="submit" onClick={this._submitContactForm}>
                        Submit
                    </Button>
                </div>
            </form>
        );
    }

    private _inputChangeHandler = (event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>, key: string) => {
        const updatedFormData = { ...this.state.contactForm };
        switch (key) {
            case "email":
                updatedFormData.email = event.target.value;
                break;
            case "phone":
                updatedFormData.phone = event.target.value;
                break;
            case "message":
                updatedFormData.message = event.target.value;
                break;
            case "name":
                updatedFormData.name = event.target.value;
                break;
        }
        this.setState({ contactForm: updatedFormData });
    };

    private _submitContactForm = (event: React.MouseEvent<HTMLButtonElement, MouseEvent>): void => {
        event.preventDefault();
        console.log(this.state.contactForm);
    };
}

export default contactForm;

I don't want to compare my object keys with switch case. Is there any generic approach for changing values on input change for the defined state? e.g.: in below code I am trying to match key from parameter in method _inputChangeHandler but it throws error

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ name: string; email: string; message: string; phone: string; }'

const updatedFormData = { ...this.state.contactForm };
updatedFormData[key] = event.target.value;
this.setState({ contactForm: updatedFormData });

Thanks


Solution

  • try like this

    this.setState({ contactForm: {...this.state.contactForm, [key]: event.target.value} });
    

    @Ajay Verma

    you could set the name attribute of the TextField and then you can get the key from the event.

    like this

    ...
    private _inputChangeHandler = (event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
        const key = event.target.name;
    ...
    <TextField
        value={this.state.contactForm.phone}
        name="phone"
        onChange={this._inputChangeHandler}
        type="phone"
        label="Phone Number"
        required
    />
    ...