Search code examples
reactjsmaterial-uimenuitemreact-typescript

How to Assign Custom Types to Material UI TextField MenuItem Values in React Typescript


I have a type conflict in my code, and I'm not sure if a simple casting could solve my problem or if there is something fundamentally wrong with my code.

import React from "react";
import TextField from "@mui/material/TextField";
import MenuItem from "@mui/material/MenuItem";

interface Store {
  storeId: string;
  storeName: string;
}

const mockApi: Store[] = [
  {
    storeId: "1",
    storeName: "Store 1"
  },
  {
    storeId: "2",
    storeName: "Store 2"
  },
  {
    storeId: "3",
    storeName: "Store 3"
  }
];

export default function App() {
  const [selectedStore, setSelectedStore] = React.useState<Store>();
  const [stores, setStores] = React.useState<Store[]>([]);

  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setSelectedStore(event.target.value); // Type conflict here string not a Store
  };

  React.useEffect(() => {
    setStores(mockApi);
    setSelectedStore(mockApi[1]);
  }, []);

  return (
    <div className="App">
      <TextField
        id="outlined-select-currency"
        select
        label="Store"
        value={selectedStore}
        onChange={handleChange}
        size="small"
        style={{ width: 200 }}
        fullWidth
      >
        {stores &&
          stores.map((store) => (
            <MenuItem key={store.storeId} value={store}> // type conflict here Store is not a string
              {store.storeName}
            </MenuItem>
          ))}
      </TextField>
      {selectedStore && <div>Store name: {selectedStore.storeName}</div>}
    </div>
  );
}

I got the same code working in JS in this codesandbox

And here is my code (not working) in TS in this codesandbox


Solution

  • Instead of using the entire store object as the value just use store.storeId. You will also need to change the value prop of the text field to selectedStore.storeId.

    see: https://codesandbox.io/s/silent-fire-irpjz