Me gustaría crear un componente súper general que se pueda construir con cualquier tipo de elemento. es decir, me gustaría hacer algo como esto:
const Wrapper = React.createClass({ render() { const { props } = this; const elementType = props.elementType; return ( <{elementType} className={className}> {props.children} </{elementType}> ); } });pero, por supuesto, React se enoja mucho cuando intento esto. ¿Hay alguna forma de construir un componente con tipos de HTML por decidir?
Puede usar React.createElement para lograr eso (después de todo, JSX solo proporciona azúcar sintáctico para ello).
Algo como eso:
const myElement = React.createElement( /* type */ props.elementType, //must be a string or a React Component class /* props object */ { className: className }, /* You can pass children to the third parameter also. */ props.children ); return myElement;Esto depende mucho de qué tipo de elementType sea. En JSX, puede pasar un componente personalizado o una cadena (por ejemplo, h1 , p ) como una "etiqueta". En cualquier caso, no desea colocar llaves {} alrededor de la etiqueta. Ejemplo muy simple:
// Usually you want to import this. (This is just a stateless component) const Element = (props) => <em>{props.children}</em>; class Example extends React.Component { constructor() { super(); this.state = { element1: 'h1', element2: Element }; } render() { return( <div> <this.state.element1>Hello!</this.state.element1> <this.state.element2>World!</this.state.element2> </div> ); } } ReactDOM.render(<Example />, document.getElementById('View')); <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id='View'></div> Si desea usar una cadena como referencia a un componente personalizado, deberá usar JavaScript nativo con createElement / cloneElement de React.
Sí, puede, incluso con JSX si lo desea.
El truco es entender cómo se traduce JSX en las llamadas React.createElement :
<div/> se convierte en React.createElement('div') .<SomeComponent/> se convierte en React.createElement(SomeComponent) . Ahora imagina si asignas var SomeComponent = 'div' . Entonces se aplicaría la regla de mayúsculas (pasando la variable a createElement ), pero tendrá el mismo efecto que la primera regla (¡porque la variable hace referencia a una cadena)!
Así es como puede verse en una situación práctica:
let Child = ({EL,thing}) => <EL className="helper-thing">{{ thing.name }}</EL> let ListParent = ({things}) => <ul> {things.map(t => <Child EL='li' thing={t}/>)} </ul> let ArticleParent = ({things}) => <article> {things.map(t => <Child EL='p' thing={t}/>)} </article>Consulte los documentos oficiales sobre cómo elegir el tipo en tiempo de ejecución para obtener un enfoque ligeramente diferente, quizás más limpio, que capitaliza la propiedad dentro del componente secundario.