0

When I make a selection from the dropdown I saved the selected value to type then when I click the button I add an object to drums, I map over thee drums and based on the type I want to render the component with the same name.

Sandbox here

import React, { useState } from "react";
import uuid from "react-uuid";
import "./styles.css";

const Snare = () => {
  return <div>Snare</div>;
};

const Gong = () => {
  return <div>Gong</div>;
};

export default function App() {
  const [drums, setDrums] = useState([]);
  const [type, setType] = useState();
  return (
    <div className="App">
      {drums.map((Drum, index) => (
        <Drum.type /> // Why cant I use `.type`?
      ))}
      <label>
        Drum type to add:
        <select onChange={e => setType(e.target.value)} value={type}>
          <option value="">Select...</option>
          <option value="Snare">Snare</option>
          <option value="Gong">Gong</option>
        </select>
        <button
          onClick={() => {
            setDrums([...drums,
              {
                id: uuid(),
                type
              }
            ]);
          }}
        >
          Add drum
        </button>
      </label>
    </div>
  );
}

2 Answers 2

1

In your case Drum.type is not a component but a string, you need to maintain a map of the string to component and then render it

const map = {
  Snare: Snare,
  Gong: Gong
};

export default function App() {
  const [drums, setDrums] = useState([]);
  const [type, setType] = useState();
  return (
    <div className="App">
      {drums.map((Drum, index) => {
        const Component = map[Drum.type];
        return <Component key={index}/>;
      })}
      <label>
        Drum type to add:
        <select onChange={e => setType(e.target.value)} value={type}>
          <option value="">Select...</option>
          <option value="Snare">Snare</option>
          <option value="Gong">Gong</option>
        </select>
        <button
          onClick={() => {
            setDrums([
              ...drums,
              {
                id: uuid(),
                type
              }
            ]);
          }}
        >
          Add drum
        </button>
      </label>
    </div>
  );
}

Working demo

Sign up to request clarification or add additional context in comments.

Comments

1

That's because the type is a string.

You could create a mapping to solve this and use React.createElement().

Something like:

const mapping = {
  'Snare': Snare,
  'Gong': Gong
}

{ drums.map(({ type }, index) => (
    React.createElement(mapping[type], { key: index })
  ))
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.