How can you render a react component using dynamic name? - reactjs

Here's what I've tried and all it does is insert html with the theme value as the tag. It doesn't create an actual React Component.
!!! Let's assume the theme name is 'rounded'
renderTemplate(){
const store = JSON.parse(localStorage.getItem('store'));
const template = this.state.product.template;
const Theme = `${template.charAt(0).toUpperCase()}${template.slice(1)}`;
return <Theme store={this.props.store} product={this.state.product} />;
}
render(){
return (
<div>
{ _.isEmpty(this.state.product) ?
'LOADING'
:
this.renderTemplate()
}
</div>
)
}
Also, I read in another question that someone mentioned something about it can't be wrapped in an html element so I also tried this unsuccessfully:
render(){
return (
_.isEmpty(this.state.product) ?
<div>LOADING</div>
:
this.renderTemplate()
)
}
Both cases just render html elements like (from console inspector):
<div class="row">
<rounded store="XXXXX" product="XXXXX"></rounded>
<rounded store="XXXXX" product="XXXXX"></rounded>
<rounded store="XXXXX" product="XXXXX"></rounded>
</div>
In React Inspector:
<div class="row">
<Rounded store="XXXXX" product="XXXXX"></Rounded>
<Rounded store="XXXXX" product="XXXXX"></Rounded>
<Rounded store="XXXXX" product="XXXXX"></Rounded>
</div>
And if it helps the React Console shows each of the divs children as:
$$typeof: Symbol(react.element)
Empty object
EDIT !!!!
Import Rounded from ‘./Themes/Rounded’;
In case it is missed here... what I need to accomplish is rendering an actual react component named <Rounded />
EDIT 2 !!!!
Here is the complete code (minus anything irrelevant):
import React from 'react';
import ReactDOM from 'react-dom';
// IMPORT THEMES
import {
Rounded,
Square,
[Other themes here]
} from './Themes';
class MyClass extends React.Component {
constructor(props){
super(props);
this.state = {
product: {}
};
}
renderTemplate(){
const template = this.state.product.template;
const Theme = `${template.charAt(0).toUpperCase()}${template.slice(1)}`;
return <Theme product={this.state.product} />;
}
render(){
return (
_.isEmpty(this.state.product) ?
<div>LOADING</div>
:
this.renderTemplate()
)
}
}
export default MyClass;

Here's how you do it!
import React from 'react';
import ReactDOM from 'react-dom';
// IMPORT THEMES
import * as Themes from './Themes';
class MyClass extends React.Component {
constructor(props){
super(props);
this.state = {
product: {}
};
}
renderTemplate(){
const template = this.state.product.template;
const Theme = Themes[template.charAt(0).toUpperCase() + template.slice(1)];
return <Theme product={this.state.product} />;
}
render(){
return (
_.isEmpty(this.state.product) ?
<div>LOADING</div>
:
this.renderTemplate()
)
}
}
export default MyClass;
Notice the import * as which automatically sticks all classes in an array for you. An array of functions I should mention. So now Themes[] is a direct reference to a function and not just a string.

Related

Why does react display my functional component at the bottom of my page?

My main page looks like this :
import React from "react";
import { Fragment } from "react";
import ModalA from "../components/Modal/ModalOptionA";
export default class AePage extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<Fragment>
<div className="grid-intro">
<div className="text-intro">
Some Text
</div>
<div className="modal-component-insert">
<ModalA show={true}/>
</div>
<div className="text-outro">
Some text
</div>
</div>
</Fragment>
)
}
}
And my component looks like this :
import React from "react";
import ReactDOM from "react-dom";
const Modal = ({ show, closed}) => {
return (
ReactDOM.createPortal(
<>
<div className="modal">
My Component
</div>
</>,
document.body
)
)
}
export default Modal;
The code above display something like :
Some Text
Some Text
My Component
Why does my component not display between the texts ? Is there a specific way for React to display this component between my divs ?
That is what ReactDOM.createPortal is for. It will always move things to the bottom of the DOM. That way, you can then position it above everything else using CSS.
It seems you don't really need that, so I'd just replace your code for the Modal component with:
import React from "react";
const Modal = ({ show, closed}) => {
return (
<div className="modal">
My Component
</div>
)
}
export default Modal;

How do I change the attributes of a dependencies?

So I am trying to learn how to use the npm library, and I found this carousel. I implemented it into my project, but I am unsure about how to change the attributes. Here is the doc: https://www.npmjs.com/package/react-responsive-carousel
and here is my current code:
import React, { Component } from 'react';
import "react-responsive-carousel/lib/styles/carousel.min.css";
import { Carousel } from 'react-responsive-carousel';
import Project1 from './Project1'
import Project2 from './Project2'
class Projects extends Component {
constructor(props){
super(props)
this.state = {
showArrows: 'false',
showIndicators: 'false'
}
}
render() {
const styles = {
display: 'none'
}
return (
<Carousel>
<div>
<Project1 />
</div>
<div>
<img style = {styles}src="http://lorempixel.com/output/cats-q-c-640-480-1.jpg" />
<Project2 />
</div>
</Carousel>
);
}
};
export default Projects
You can do it as you will do for normal components.
<Carousel showArrows={false} showIndicators={false}>
Refer for demos.

How to send data from one component to another in nextjs

I'm working in nextjs.I have header component and in order to show header in all other pages ,overrided app.js with _app.js .Header has 2 navigation link usersList and users.
Now I want to send data from header component to another page say usersList and users on click of submit in header.How we can achieve that .
I know that we can use context .I'm using class based component don't know weather we can use context.
Is there any other solution to this problem..
Please help
header.js
class HeaderComponent extends Component {
onSearch(event){
//some code
}
render() {
return (
<div className="navbar">
<Input id="search-input" className="text-box" placeholder="Enter name or Email.." onKeyDown={($event)=>this.onSearch($event)} prefix={<Icon type="search" onClick={()=>this.onSearch} ></Icon>}></Input>
</div>
)
}
}
export default HeaderComponent
Layout.js
import React, { Component } from 'react';
import Header from './Header';
class Layout extends Component {
render () {
const { children } = this.props
return (
<div className='layout'>
<Header />
{children}
</div>
);
}
}
_app.js
import React from 'react';
import App from 'next/app';
import Layout from '../components/Layout';
export default class MyApp extends App {
render () {
const { Component, pageProps } = this.props
return (
<Layout>
<Component {...pageProps} />
</Layout>
)
}
}
userList.js
class AppUser extends Component {
render() {
return (
<Table
rowKey={data._id}
columns={this.columns1}
onExpand={this.onExpand}
dataSource={data}
/>
)
}
}
EDIT :
can we achieve it through props
You can use ReactRedux to create a store and have it accessible from all components.
https://redux.js.org/api/store [1]

Wrapping React components in other React components that mange behavior props.

I found this code online and because I'm new to React wanted to know how to use it without getting this error.
this.props.children is not a function
From what I gather its listing to the body scroll position and trying to pass it as props to any React children its wrapped around. Am I correct ?
If so why the above error when I use it like below.
import React, {Component} from 'react';
import Nav from './nav';
import styles from '../../styles/header.scss';
import bgCover from '../../images/homeslider.jpg';
import Scroll from '../utils/scroll';
export default class Header extends Component{
render(){
return(
<Scroll>
<div id='header'>
<div className="container">
<img src={bgCover} id='bg-cover' alt="background-image" />
<div id="temp-text">HEADER</div>
<Nav />
</div>
</div>
</Scroll>
)
}
}
This is the scroll.js file
import React, {Component} from 'react';
export default class Scroll extends Component {
constructor(props) {
super(props);
this.state = { scrollTop: 0,
scrollLeft: 0 };
window.addEventListener('scroll', event => {
this.setState({ scrollTop: document.body.scrollTop,
scrollLeft: document.body.scrollLeft});
});
}
render() {
return this.props.children(this.state.scrollTop, this.state.scrollLeft)
}
}
As Andrew mentions, this.props.children is not a function. In your render function, if you wanted to render the children components, then your render would be written something like this.
render() {
return (
<div>
{this.props.children}
</div>
)
}
In your example, the code above would place this JSX block
<div id='header'>
<div className="container">
<img src={bgCover} id='bg-cover' alt="background-image" />
<div id="temp-text">HEADER</div>
<Nav />
</div>
</div>
into your Scroll component, because they are the children (nested) components.
Now, it looks like you want to pass props to your children components. You can do this by adding accessing React.Children.
An nice example of passing a function as a prop to all children components can be found here :
doSomething: function(value) {
console.log('doSomething called by child with value:', value);
}
const childrenWithProps = React.Children.map(this.props.children,
(child) => React.cloneElement(child, {
doSomething: this.doSomething
})
);
return <div>{childrenWithProps}</div>

Using material-ui with ecmascript6

I jus find material-ui and I'm trying to add some components in the following way
import React from 'react';
import mui from 'material-ui';
import injectTapEventPlugin from 'react-tap-event-plugin';
import PropertiesList from './../components/propertylist.jsx';
import Filters from './../components/filter.jsx';
import Properties from './../models/PropertiesModel.js';
import Toolbar from './../components/toolbar.jsx';
var AppBar = mui.AppBar;
var IconButton = mui.IconButton;
var NavigationClose = mui.NavigationClose;
var ThemeManager = new mui.Styles.ThemeManager();
var FlatButton = mui.FlatButton;
injectTapEventPlugin();
class TransProperties extends React.Component {
constructor(props){
super(props);
}
render() {
return <div className="row">
<div className="col-lg-9">
<AppBar
title="Title"
iconElementLeft={<IconButton><NavigationClose /></IconButton>}
iconElementRight={<FlatButton label="Save" />} />
<PropertiesList url="/properties.json"/>
</div>
<div className="col-lg-3">
<Filters/>
</div>
</div>;
}
handleTouchTap() {
alert("oh hi");
}
}
export default TransProperties
but I get an error Uncaught TypeError: Cannot read property 'spacing' of undefined
which refers to
getStyles: function getStyles() {
var spacing = this.context.muiTheme.spacing;...}
What did I missed?
You're likely missing the contextType on your component, which makes muiTheme available.
Your component should look something like this:
class ExampleComponent extends React.Component {
getStyles() {
...
let spacing = this.context.muiTheme.spacing;
...
}
render() {
return (
<div style={this.getStyles()} />
);
}
}
// Don't forget this little nugget
ExampleComponent.contextTypes = {
muiTheme: React.PropTypes.object
}

Resources