Динамический рендер компонентов

Редактировал(а) Alexandr Fokin 2023/12/29 14:48

 React + TypeScript
 import { useState, createElement, ElementType } from 'react'

interface componentProp {
    selectedComponent: string,
    prop1: number,    
    onClick: (state: componentProp) => void
};

function Component1(prop: componentProp) {
    return (
        <div>
            <p>component1 {prop.prop1}</p>
            <button
               onClick={() => { prop.onClick({ ...prop, prop1: prop.prop1 + 1 }) }}
            >
                Increment
            </button>
            <button
               onClick={() => { prop.onClick({ ...prop, selectedComponent: "c2" }) }}
            >
                To component2
            </button>
            <button
               onClick={() => { prop.onClick({ ...prop, selectedComponent: "unknow name" }) }}
            >
                Bad component
            </button>
        </div>
    )
}
function Component2(prop: componentProp) {
    return (
        <div>
            <p>component2 {prop.prop1}</p>
            <button
               onClick={() => { prop.onClick({ ...prop, prop1: prop.prop1 + 1 }) }}
            >
                Increment
            </button>
            <button
               onClick={() => { prop.onClick({ ...prop, selectedComponent: "c1" }) }}
            >
                To component1
            </button>
        </div>
    )
}

const mapping = new Map<string, ElementType>()
    .set("c1", Component1)
    .set("c2", Component2);

function App() {

    const [state, setState] = useState<componentProp>(
        {
            selectedComponent: "c1",
            prop1: 10,
            onClick: (q) => {
                setState(q)
            }
        });

    const selectedComponent = mapping.get(state.selectedComponent);

    if (selectedComponent === undefined) {
        return (<>
            <div>Not defined "{state.selectedComponent}"</div>
       </>);
    }

  return (
     <>
          <div>
              {createElement(selectedComponent, state) }
          </div>
     </>
  )
}

export default App
  
Теги: