0

This may be a complete noob question, but I am having trouble figuring this out. I have a React component, and inside its render method, I want to render some dynamically passed in components (through props).

Here's my return from the render method (ES6, transpiled with Babel)

return (
    <div className={openState}>
    /* Shortened for brevity*/
    {this.props.facets.map(function(f) {
        var CompName = facetMap[f.type]
        return <CompName key={f.id} />
    })}
    /* Shortened for brevity*/
    </div>
)

facetMap is simply a map to match up a string to the "type" passed in. I can't seem to get the components to actually render on the page.

I had the result of the .map() method stored in a var, and then logged that to the console, and it showed an array of components. However {facetComponents} in the render method had the same results.

EDIT, for those interested in the solution

Because I genuinely could not find an answer anywhere, here's my completed solution, thanks to @Mathletics

//Components imported using ES6 modules
import OCFacetText from "./oc-facet-text"
// Etc... 

//Later on, in my render method:
let facetMap = {
    "text":         OCFacetText,
    "number":       OCFacetNumber,
    "numberrange":  OCFacetNumberRange,
    "boolean":      OCFacetBoolean,
    "checkbox":     OCFacetCheckbox,
    // Etc, etc... 
}

let facetComps = facets.map(function(f) {
    var CompName = facetMap[f.type]
    return <CompName key={f.id} />
})

//Finally, to render the components:
return (
    <div className={openState}>
    /* Shortened for brevity*/
        {facetComps}
    /* Shortened for brevity*/
    </div>
)
Aaron Wagner
  • 317
  • 1
  • 3
  • 15
  • If you just render ONE component does it work? – Evan Davis Mar 02 '16 at 19:28
  • Just rendering the component on the page? Yes, that works. Basically the use case is allowing these components to be reused and dynamically specified. – Aaron Wagner Mar 02 '16 at 19:44
  • Is `facetMap` a set of strings or a set of Component classes? [Dynamic component names](http://stackoverflow.com/questions/29875869) have been well covered on SO. – Evan Davis Mar 02 '16 at 19:58
  • Just strings. I actually ran across that question in my searching yesterday. I want my developers to be able to pass in 'text' instead of 'OCFacetText'. – Aaron Wagner Mar 02 '16 at 20:10
  • I'm not sure if we understand each other; of course the _keys_ of `facetMap` are strings, but if you lookup `facetMap['text']` it should return a component class `OCFacetText`, __not__ the string `'OCFacetText'`. – Evan Davis Mar 02 '16 at 20:16
  • That doesn't really solve my problem though, because the references to the components are still hard coded. Can you provide an answer that demonstrates what you mean, in case (probably) that I am misunderstanding? – Aaron Wagner Mar 02 '16 at 22:24
  • 1
    Possible duplicate of [React / JSX Dynamic Component Name](http://stackoverflow.com/questions/29875869/react-jsx-dynamic-component-name) – Evan Davis Mar 03 '16 at 17:44

2 Answers2

2

Annoying one.

If you want dynamic component names you'll have to utilize React.createElement(CompName), where CompName is a string or the class object.

By default react will look for a component named CompName in your above example.

So your render function would look like so:

return (
    <div className={openState}>
    /* Shortened for brevity*/
    {this.props.facets.map(function(f) {
        var CompName = facetMap[f.type]
        return React.createElement(CompName, {key: f.id}) />
    })}
    /* Shortened for brevity*/
    </div>
)
rguerrettaz
  • 836
  • 8
  • 12
2

From what I can gather, it sounds like your facetMap is a collection of strings:

var facetMap = {text: 'OCFacetText'}

but it should actually return component classes:

var OCFacetText = React.createClass({...});

var facetMap = {text: OCFacetText};

Then (and only then) you will need to use the createElement method to construct your component dynamically:

var CompName = facetMap[f.type]; // must be a FUNCTION not a string
return React.createElement(CompName, {key: f.id}) />
Evan Davis
  • 35,493
  • 6
  • 50
  • 57
  • FYI, this is exactly the solution that is covered in the question I linked you, http://stackoverflow.com/questions/29875869/react-jsx-dynamic-component-name – Evan Davis Mar 03 '16 at 17:44
  • I actually saw that answer but it wasn't super helpful for this context, though I can see how the two overlap. – Aaron Wagner Mar 03 '16 at 17:55
  • The two overlap because they are _the same_. It is exactly the same question. – Evan Davis Mar 03 '16 at 18:07