reactjs - Använda uppräkningar i React-select


Jag vill visa en dropdown i React med följande uppräkning. Idén är att förhindra att använda slumpmässiga strängar som nycklar i min <select>. Nycklarna bör begränsas till Stooges.larry, Stooges.curly och Stooges.moe:

const Stooges = {
  larry: "Larry Fine",
  curly: "Curly Howard",
  moe: "Moe Howard"
};

Här är koden för mitt val, som fungerar alldeles utmärkt:

<select value={stooge} onChange={handleChange}>
  {Object.keys(Stooges).map(key => (
    <option key={key} value={key}>
      {Stooges[key]}
    </option>
  ))}
</select>

Problemet uppstår när jag försöker ställa in startvärdet för rullgardinsmenyn - jag måste använda en hårdkodad nyckel:

const [stooge, setStooge] = React.useState('larry');

Jag kan mjuka upp detta lite genom att välja den första nyckeln:

const keys = Object.keys(Stooges);
const [stooge, setStooge] = React.useState(keys[0]);

Men det här känns fortfarande fel. Jag kan inte avgöra från key[0] vem jag väljer.

Finns det ett bättre sätt att hantera uppräkningar i detta användningsfall? Jag har försökt med strängenumereringar i TypeScript, men de har samma problem:

enum Stooges {
  larry = "Larry Fine",
  curly = "Curly Howard",
  moe = "Moe Howard"
}

Vänligen se min CodeSandbox här.

Svar #1

För en enum Animals:

enum Animal{
  Cat= "Cat",
  Dog= "Dog",
  Hamster= "Hamster"
}

Vi kan definiera en generisk funktion getEnumKeys som hämtar arrayen av nycklar i en enum:

// Inspired from https://github.com/microsoft/TypeScript/issues/30611#issuecomment-570773496
function getEnumKeys<
    T extends string,
    TEnumValue extends string | number,
>(enumVariable: { [key in T]: TEnumValue }) {
    return Object.keys(enumVariable) as Array<T>;
}

Vi kan sedan gå igenom listan över nycklar för Animal som returneras av getEnumKeys-funktionen i select.

import React from "react";

enum Animal {
  Cat = "Cat",
  Dog = "Dog",
  Hamster = "Hamster"
}

export default function App() {
  const [currentAnimal, setCurrentAnimal] = React.useState<Animal>(Animal.Cat);
  return (
    <select
      value={currentAnimal}
      onChange={(e) => {
        setCurrentAnimal(Animal[e.target.value as keyof typeof Animal]);
      }}
    >
      {getEnumKeys(Animal).map((key, index) => (
        <option key={index} value={Animal[key]}>
          {key}
        </option>
      ))}
    </select>
  );
}

function getEnumKeys<
   T extends string,
   TEnumValue extends string | number,
>(enumVariable: { [key in T]: TEnumValue }) {
    return Object.keys(enumVariable) as Array<T>;
}

Kod Sandlåda: https://codesandbox.io/s/unruffled-sinoussi-pr7dpf?file=/src/App.tsx:0-600

Svar #2

I brist på en bättre lösning har jag tagit följande tillvägagångssätt. Jag kan åtminstone välja rätt enum efter namn: Stooges.larry.id:

const Stooges = {
  larry: {
    id: "larry",
    name: "Larry Fine"
  },
  curly: {
    id: "curly",
    name: "Curly Howard"
  },
  moe: {
    id: "moe",
    name: "Moe Howard"
  }
};

function App() {
  const [stooge, setStooge] = React.useState(Stooges.larry.id);

  const handleChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
    setStooge(event.target.value);
  };

  return (
    <div className="App">
      <select value={stooge} onChange={handleChange}>
        {Object.keys(Stooges).map(key => (
          <option key={key} value={key}>
            {Stooges[key].name}
          </option>
        ))}
      </select>
    </div>
  );
}

Här är den nya CodeSandbox: https://codesandbox.io/embed/wqj2q94o2k

Relaterade artiklar