DEV Community

Touhidul Shawan
Touhidul Shawan

Posted on

Need help to fix a problem

I am understanding the error in my code that string can not be used as an index of type {username: string; password: string;}. But how can I fix this now? I want to handle multiple input element value on change, how can I do this here in my code on handleChange function. !! warning I am new in typescript.
Here is my code for Login.tsx

import * as React from "react";
import { useState } from "react";
import InputField from "./InputField";

interface User {
  username: string;
  password: string;
}

const Login: React.FC = () => {
  // account state
  const [account, setAccount] = useState<User>({
    username: "",
    password: "",
  });

  function handleChange(evt: React.FormEvent<HTMLInputElement>) {
    // extract name and value property of current input element
    const { name, value } = evt.currentTarget;
    const accountCopy = { ...account }; // make copy of current account;
    accountCopy[name] = value; // update value from input element value
    setAccount(accountCopy);
  }

  function handleSubmit(evt: React.FormEvent<HTMLFormElement>) {
    evt.preventDefault();
    alert(`Hi ${account.username} with pass ${account.password}`);
  }

  return (
    <div className="col-8 m-auto mt-4 py-2">
      <h1>Login</h1>
      <form onSubmit={handleSubmit}>
        <InputField
          label="Username"
          name="username"
          type="text"
          value={account.username}
          onChange={handleChange}
        />
        <InputField
          label="Password"
          name="password"
          type="password"
          value={account.password}
          onChange={handleChange}
        />
        <button type="submit" className="btn btn-primary">
          Login
        </button>
      </form>
    </div>
  );
};

export default Login;
Enter fullscreen mode Exit fullscreen mode

Code for InputField.tsx

import * as React from "react";

interface Props {
  name: string;
  label: string;
  value: string;
  type: string;
  onChange: (evt: React.FormEvent<HTMLInputElement>) => void;
}

const InputField: React.FC<Props> = ({
  name,
  label,
  value,
  type,
  onChange,
}) => {
  return (
    <div className="form-group">
      <label htmlFor="name">{label}</label>
      <input
        name={name}
        id={name}
        type={type}
        className="form-control"
        value={value}
        onChange={(evt) => onChange(evt)}
        required
      />
    </div>
  );
};

export default InputField;
Enter fullscreen mode Exit fullscreen mode

Top comments (2)

Collapse
 
shaegi profile image
Marvin Semmelroth

Hi,
I believe what youre looking for is keyof

Since typescript doesn't know that name is a key of your object you can cast the name to be keyof account by simply changing the line

    accountCopy[name] = value; // update value from input element value

to

    accountCopy[name as keyof User] = value; // update value from input element value

hope that helps :)

Collapse
 
touhidulshawan profile image
Touhidul Shawan • Edited

Thanks, ❤ . This was very helpful. It worked