Home > Enterprise >  React Typescript. Render proper Icon based on dynamic props value
React Typescript. Render proper Icon based on dynamic props value

Time:05-09

I have a span in my JSX in which I want to render a proper icon based on the dynamic props value

<span>{IconToProductMap(value)}</span>

This is how this function looks like

const IconToProductMap = (value: string) => {
  if (value === 'sampleValue') {
    return <Icon type={IconType.card} />
  }
  if (value === 'sampleValue2') {
    return <Icon type={IconType.card2} />
  }
  return <Icon type={IconType.card3} />
}

This solution is really bad and I'd like to be able to dynamically assign the value so that I can render the icon like this

    <span>{IconToProductMap[value]}</span>

To achieve that I've created the mapper object

const mapper = {
  possiblePropsValue1: IconType.card,
  possiblePropsValue2: IconType.bag,
  possiblePropsValue3: IconType.arrow_left,
}

and used it like so:

    <span>{mapper[value]}</span>

The problem is that TS throws

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ possiblePropsValue1: IconType; possiblePropsValue2: IconType; possiblePropsValue3: IconType; }'. No index signature with a parameter of type 'string' was found on type '{ possiblePropsValue1: IconType; possiblePropsValue2: IconType; possiblePropsValue3: IconType; }'

I'd be really glad if someone could explain how to properly fix that. Thanks in advance

CodePudding user response:

You should define mapper with a proper type

const mapper: Record<string, JSX.Element> = {
  possiblePropsValue1: IconType.card,
  possiblePropsValue2: IconType.bag,
  possiblePropsValue3: IconType.arrow_left,
}

Record<key,value> receives key as string, value as JSX.Element which is from your IconType returned value.

CodePudding user response:

You can use an enum to simplify string parameters & better manage the icon types. You can store the strings (sampleValue) in the enum.

enum IconType {
  card = "card",
  bag = "bag",
  arrow_left = "arrow_left"
}

interface IconProps {
  iconType: IconType;
}

const Icon = (props: IconProps) => {
  const { iconType } = props;
  return <div>{iconType}</div>; // just for demonstration
};

export default function App() {

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <Icon iconType={IconType.bag} />
    </div>
  );
}
  • Related