score:246
<mycomponent />
compiles to react.createelement(mycomponent, {})
, which expects a string (html tag) or a function (reactclass) as first parameter.
you could just store your component class in a variable with a name that starts with an uppercase letter. see html tags vs react components.
var mycomponent = components[type + "component"];
return <mycomponent />;
compiles to
var mycomponent = components[type + "component"];
return react.createelement(mycomponent, {});
score:-2
i used a bit different approach, as we always know our actual components so i thought to apply switch case. also total no of component were around 7-8 in my case.
getsubcomponent(name) {
let customprops = {
"prop1" :"",
"prop2":"",
"prop3":"",
"prop4":""
}
switch (name) {
case "component1": return <component1 {...this.props} {...customprops} />
case "component2": return <component2 {...this.props} {...customprops} />
case "component3": return <component3 {...this.props} {...customprops} />
}
}
score:-2
edit: other answers are better, see comments.
i solved the same problem this way:
...
render : function () {
var componenttorender = 'component1name';
var componentlookup = {
component1name : (<component1 />),
component2name : (<component2 />),
...
};
return (<div>
{componentlookup[componenttorender]}
</div>);
}
...
score:0
suspose we wish to access various views with dynamic component loading.the following code gives a working example of how to accomplish this by using a string parsed from the search string of a url.
lets assume we want to access a page 'snozberrys' with two unique views using these url paths:
'http://localhost:3000/snozberrys?acomponent'
and
'http://localhost:3000/snozberrys?bcomponent'
we define our view's controller like this:
import react, { component } from 'react';
import reactdom from 'react-dom'
import {
browserrouter as router,
route
} from 'react-router-dom'
import acomponent from './acomponent.js';
import cobcomponent sole from './bcomponent.js';
const views = {
acomponent: <acomponent />,
console: <bcomponent />
}
const view = (props) => {
let name = props.location.search.substr(1);
let view = views[name];
if(view == null) throw "view '" + name + "' is undefined";
return view;
}
class viewmanager extends component {
render() {
return (
<router>
<div>
<route path='/' component={view}/>
</div>
</router>
);
}
}
export default viewmanager
reactdom.render(<viewmanager />, document.getelementbyid('root'));
score:0
assuming you are able to export * from components like so...
// src/components/index.js
export * from './home'
export * from './settings'
export * from './sitelist'
you can then re-import * into a new comps object, which can then be used to access your modules.
// src/components/dynamicloader.js
import react from 'react'
import * as comps from 'components'
export default function ({component, defaultprops}) {
const dynamiccomponent = comps[component]
return <dynamiccomponent {...defaultprops} />
}
just pass in a string value that identifies which component you want to paint, wherever you need to paint it.
<dynamicloader component='home' defaultprops={someprops} />
score:2
assume we have a flag
, no different from the state
or props
:
import componentone from './componentone';
import componenttwo from './componenttwo';
~~~
const compo = flag ? componentone : componenttwo;
~~~
<compo someprop={somevalue} />
with flag compo
fill with one of componentone
or componenttwo
and then the compo
can act like a react component.
score:4
having a map doesn't look good at all with a large amount of components. i'm actually surprised that no one has suggested something like this:
var componentname = "stringthatcontainscomponentname";
const importedcomponentmodule = require("path/to/component/" + componentname).default;
return react.createelement(importedcomponentmodule);
this one has really helped me when i needed to render a pretty large amount of components loaded in a form of json array.
score:7
with the introduction of react.lazy, we can now use a true dynamic approach to import the component and render it.
import react, { lazy, suspense } from 'react';
const app = ({ componentname, ...props }) => {
const dynamiccomponent = lazy(() => import(`./${componentname}`));
return (
<suspense fallback={<div>loading...</div>}>
<dynamiccomponent {...props} />
</suspense>
);
};
this approach makes some assumptions about the file hierarchy of course and can make the code easy to break.
score:9
if your components are global you can simply do:
var nameofcomponent = "somecomponent";
react.createelement(window[nameofcomponent], {});
score:9
for a wrapper component, a simple solution would be to just use react.createelement
directly (using es6).
import raisedbutton from 'mui/raisedbutton'
import flatbutton from 'mui/flatbutton'
import iconbutton from 'mui/iconbutton'
class button extends react.component {
render() {
const { type, ...props } = this.props
let button = null
switch (type) {
case 'flat': button = flatbutton
break
case 'icon': button = iconbutton
break
default: button = raisedbutton
break
}
return (
react.createelement(button, { ...props, disabletouchripple: true, disablefocusripple: true })
)
}
}
score:9
across all options with component maps i haven't found the simplest way to define the map using es6 short syntax:
import react from 'react'
import { photostory, videostory } from './stories'
const components = {
photostory,
videostory,
}
function story(props) {
//given that props.story contains 'photostory' or 'videostory'
const specificstory = components[props.story]
return <specificstory/>
}
score:11
i figured out a new solution. do note that i am using es6 modules so i am requiring the class. you could also define a new react class instead.
var components = {
example: react.createfactory( require('./examplecomponent') )
};
var type = "example";
newcomponent() {
return components[type]({ attribute: "value" });
}
score:27
there should be a container that maps component names to all components that are supposed to be used dynamically. component classes should be registered in a container because in modular environment there's otherwise no single place where they could be accessed. component classes cannot be identified by their names without specifying them explicitly because function name
is minified in production.
component map
it can be plain object:
class foo extends react.component { ... }
...
const componentsmap = { foo, bar };
...
const componentname = 'fo' + 'o';
const dynamiccomponent = componentsmap[componentname];
<dynamiccomponent/>;
or map
instance:
const componentsmap = new map([[foo, foo], [bar, bar]]);
...
const dynamiccomponent = componentsmap.get(componentname);
plain object is more suitable because it benefits from property shorthand.
barrel module
a barrel module with named exports can act as such map:
// foo.js
export class foo extends react.component { ... }
// dynamic-components.js
export * from './foo';
export * from './bar';
// some module that uses dynamic component
import * as componentsmap from './dynamic-components';
const componentname = 'fo' + 'o';
const dynamiccomponent = componentsmap[componentname];
<dynamiccomponent/>;
this works well with one class per module code style.
decorator
decorators can be used with class components for syntactic sugar, this still requires to specify class names explicitly and register them in a map:
const componentsmap = {};
function dynamic(component) {
if (!component.displayname)
throw new error('no name');
componentsmap[component.displayname] = component;
return component;
}
...
@dynamic
class foo extends react.component {
static displayname = 'foo'
...
}
a decorator can be used as higher-order component with functional components:
const bar = props => ...;
bar.displayname = 'bar';
export default dynamic(bar);
the use of non-standard displayname
instead of random property also benefits debugging.
score:213
there is an official documentation about how to handle such situations is available here: https://facebook.github.io/react/docs/jsx-in-depth.html#choosing-the-type-at-runtime
basically it says:
wrong:
import react from 'react';
import { photostory, videostory } from './stories';
const components = {
photo: photostory,
video: videostory
};
function story(props) {
// wrong! jsx type can't be an expression.
return <components[props.storytype] story={props.story} />;
}
correct:
import react from 'react';
import { photostory, videostory } from './stories';
const components = {
photo: photostory,
video: videostory
};
function story(props) {
// correct! jsx type can be a capitalized variable.
const specificstory = components[props.storytype];
return <specificstory story={props.story} />;
}
Source: stackoverflow.com
Related Query
- React / JSX Dynamic Component Name
- Dynamic tag name in React JSX
- React include dynamic prop value in component name
- React Component with Dynamic Tag Name Not Rendered
- Dynamic component name - React
- dynamic routing in react js, component name from a string cannot be assigned in route
- Conditionally pass a Boolean prop with a dynamic prop name to a React component
- Dynamic Component Name with props react
- Pass prop that has a dynamic name in react to child component
- How to change React component tag to jsx tag name with condition properly?
- Get component name in React
- Dynamic href tag React in JSX
- Dynamic Opacity not changing when component rerenders in react native
- React.js without JSX - "Warning: Something is calling a React component directly. Use a factory or JSX instead"
- dynamic HTML String to react component
- Do I have to save react component files with a jsx extension
- React props: Using an HTML entity within JSX dynamic content?
- Dynamic tabIndex attribute in JSX + React
- Selectively rendering optional component properties in React JSX
- React render component using its name
- React JSX vs function call to present component
- how to access vairables outside of map function in js and jsx in a React component
- Using JS React component in TypeScript: JSX element type 'MyComponent' is not a constructor function for JSX elements
- Render a React component based on its name
- Dynamic import in react not working when trying to import a component in another directory
- Component name with React hooks in DevTools
- How to get parent component name in React function component
- Styled Component dynamic tag name
- how to get current react component name inside custom react hook?
- React Access parent component name
More Query from same tag
- Clicking on a block and controlling a child
- I am trying to add an object to a nested array I have stored in my state object, but seem to have an issue with it
- How to insert setState value into useEffect hook?
- Add style/class to react-datepicker
- How to add two event for the On submit
- Regex in React email validation
- Event Source Fetch not returning Data
- SyntaxError: Unexpected token < in JSON at position 0 - React app in Rails API
- Multiple useEffect React.useEffect has missing dependencies
- Dynamically pass the JSON data in chartjs
- React hook useEffect dependency array
- setState array cause infinite loop
- Need to delete item from array using redux
- Run webpack without sudo
- Rendering component based on state/prop in React?
- when i do destructuring to initialize multiple variables via use state hook code works but it doesnt work when i do object destructuring
- How can I use date component in a React form
- Unable to fetch data with useQuery hook for a remote query that has some @client variables
- how to access a component style in react js
- How to use a bootstrap load spinner while fetching data from an external api?
- How to type a built-in function in an interface?
- With react-router, redux will not work
- How to make bundel.js execute code right on home page?
- ReactJS: How do I pass data from JSON in local storage to a component?
- Updating the state of a parent in child component in a immutable way
- How to please TS compiler using conditional React JSX components
- React: Expensive computation in useEffect blocking the rendering
- How can I map array with multiple objects and display on chart?
- Why can't i import my component from the same folder?
- React - Wrong component rendering after calling history.push