2

I'm pretty new to React, coming from an angular world. I have a scenario where I need to dynamically load a component give a searchType prop. The end user will have a dropdown of searchTypes they can pick from, this prop is passed in after they click the submit button.

I have a SearchResults component defined, which should dynamically load the appropriate component depending on the value of this.props.searchType.name

import React, { findDOMNode, Component, PropTypes } from 'react';
import Material from './Material'; // Material Search Results Component
import Vendor from './Vendor'; // Vendor Search Results Component

export default class SearchResults extends Component {
  constructor(props){
    super(props);
  }


  // searchType = {
  //  name: 'Material',
  //  id: 'MATERIAL'
  // }

  render() {
    const { searchType, items, itemsCount } = this.props;

    var ComponentName = searchType.name;

    return (
      <div className='row'>
        <h1>Search Results ({items.length}/{itemsCount})</h1>
        <ComponentName items={items} />
      </div>
    );
  }
}

SearchResults.propTypes = {
  items: PropTypes.array.isRequired
};

Now, this seems to partially work as when using the React Dev Tools in chrome I can see the provider/component show up in the DOM.. but it doesn't render.

I'm just not sure where to go next from here, or if i'm doing something wrong.

2 Answers 2

4

You're trying to use a string instead of the actual class. I think you want something like this:

var searchTypes = {
  Material,
  Vendor,
};

// ...

    var Component = searchTypes[searchType.name];

    return (
      <div className='row'>
        <h1>Search Results ({items.length}/{itemsCount})</h1>
        <Component items={items} />
      </div>
    );

Here's a simple example.

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

6 Comments

thanks this works perfectly.. One other thing i didn't mention as it was going to be the next step in this code is dynamically loading the Components ... import ComponentName from './' + ComponentName; or maybe if there is a way to extend those various components off a base class and import the entire base class and all its children? Either way, thanks for the quick response!
import declarations are static, so you can't do it that way. Eventually there'll be a dynamic module loader. For now you could dynamically generate import declarations as part of a build step. You could also create a module that imports and re-exports (in some fashion) all of the components, then import that into this component.
Actually I ended up doing an import * as Templates and then in the constructor I iterate over it and push to search types seems to work?
If you have a module that exports each of the search type components, sure. In that case I don't think you need to iterate it and copy to some other var though -- you can just do Templates[searchType.name] at that point, right?
You could have them in separate files, and have a module (let's call it components) that imports and exports them all. E.g. import Material from './material'; import Vendor from './vendor'; export default {Material, Vendor}; Then in the component you illustrated here, import Components from './components'; /* ... */ var Component = Components[searchType.name];.
|
1

You could try a switch statement.

render() {
  //...
  var component;

  switch(searchType.name){
    case "material":
      component = <Material items={items} />
    case "vendor":
      component = <Vendor items={items} />
  }

  return (
    //...

    {component}
  )
}

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.