React Component with dynamic Sub-Components - javascript

I`m creating a react dynamic dialog where you can add functionality to the Dialog.
One way of doing this was with Composition, but I did not manage to do this via composition.
I`m not very experienced on React, so this was my first approach
I got my Modal component, and the modal has
export default class KneatModal extends React.Component {
constructor() {
super();
this.state = {
open: false
}
this.components = [];
I would add components like this
import CommentField from '../../../Modal/ModalContents/CommentField.jsx'
export default class DoApprove extends React.Component {
constructor() {
super();
}
componentDidMount() {
this._buildDialog();
}
_buildDialog() {
console.log("Building the Dialog");
this.modal.components.push(CommentField);
}
In that modal renderer, i have
<ModalContent components={ this.components } />
Then i the final renderer in ModalContent i try to render all attached components
render() {
var list = this.props.components.map((Component, key) => <Component/> );
return (
<div className='modal-contents'>
{list}
</div>
)
}
But the render method does not seems to work, i`ve tryed callin Component.render() instead of the component tag, but still could not make the sub-components render. =(
Would apreciate any help. Thanks

To be even more specific, this resumes on what im attempting
import PropTypes from 'prop-types';
import React from 'react';
import MyComponent1 from './MyComponent1.jsx'
import MyComponent2 from './MyComponent2.jsx'
export default class KneatModalContent extends React.Component {
constructor() {
super();
this.components = [MyComponent1, MyComponent2];
}
render() {
return (
<div className='modal-contents'>
{this.components.map(function (component, i) {
return <{ component } key= { i } />
})}
</div>
)
}
}

Related

why my HOC Component is working properly ? #React

2 components :- ClickCounter, mouseHoverCounter !
1 HOC component to do the counting work.
earlier I was counting the click and mouse hover by writing separate counter method in each component(cliccounter,mousehovecounter),
but
now, I'm trying to pass the component into hoc counter & get the new component with only one change , where I'm passing a props to originalComponent and returning it to see the behavior but its now working...
import React, { Component } from 'react'
import updatedComponent from './hocCounter'
class ClickCounter extends Component {
constructor(props) {
super(props)
this.state = {
counter:0
}
}
ClickCounterHandler = () =>{
this.setState((prevState)=>{
return {counter:prevState.counter+1}
})
}
render() {
const count=this.state.counter
return (
<div>
<button onClick={this.ClickCounterHandler}>{this.props.name} Clicked {count} Times</button>
</div>
)
}
}
export default updatedComponent(ClickCounter)
import React, { Component } from 'react'
import updatedComponent from './hocCounter'
class HoverMouseCounter extends Component {
constructor(props) {
super(props)
this.state = {
counter:0
}
}
MouseOverCounter(){
this.setState((prevState)=>{
return {counter:prevState.counter+1}
})
}
render() {
const count=this.state.counter
return (
<div>
<h1 onMouseOver={this.MouseOverCounter.bind(this)}>{this.props.name} Hovered For {count} Time(s)</h1>
</div>
)
}
}
export default updatedComponent(HoverMouseCounter)
import React from 'react'
const updatedComponent = originalComponent => {
class newComponent extends React.Component {
render(){
return <originalComponent name='Harsh'/>
}
}
return newComponent
}
export default updatedComponent
In App.js, I'm returning
<ClickCounter></ClickCounter>
<HoverMouseCounter></HoverMouseCounter>
this only !
Check the error in the console,
index.js:1 Warning: <originalComponent /> is using incorrect casing. Use PascalCase for React components, or lowercase for HTML elements. at originalComponent
This means You are using the small letter in originalComponent
React components are expected to start with a capital letter
Try this in you HOC component
import React from 'react'
const updatedComponent = OriginalComponent => {
class NewComponent extends React.Component {
render(){
return <OriginalComponent name='Harsh'/>
}
}
return NewComponent
}
export default updatedComponent

ReactJS - State change is not observed in divs wrapped in sub component

I have the following react class. In it I'm using other react components. I'm new to React so I think I'm misunderstanding how state scope works. When menuClicked() is called, the outermost div's class will change but the innermost div's class does not. Can someone explain why?
import React, {Component} from 'react';
import Row from '../components/grid/Row.js'
import Cell from '../components/grid/Cell.js'
export default class HeaderBar extends Component {
state = {
menuOpen: false
};
constructor(props) {
super(props);
this.menuClicked = this.menuClicked.bind(this);
}
menuClicked() {
this.setState({menuOpen: !this.state.menuOpen})
};
render() {
return (
<div
className={`header-wrap ${this.state.menuOpen ? 'open' : ''}`}
>
<Row>
<Cell
c={1}
mc={12}
>
<div className={`platform-name ${this.state.menuOpen ? 'open' : ''}`}>The Platform Name</div>
</Cell>
<Cell>
<div onClick={this.menuClicked}></div>
</Cell>
</Row>
</div>
)
}
}
Added by popular demand
import React, {Component} from 'react';
export default class Row extends Component {
constructor(props) {
super();
this.children = props.children;
}
render() {
return (
<div className="r">
{this.children}
</div>
)
}
}
And the Cell class
import React, {Component} from 'react';
export default class Cell extends Component {
constructor(props) {
super();
this.props = props;
}
render() {
return (
<div
className={`c${this.props.c}`}
>
{this.props.children}
</div>
)
}
}
Problem in Row component constructor, you do this.children = props.children;, then you render this.children.
Remember constructor is called only once. So this.children is assigned once with initial value and never get updated afterwards. It’s a stale reference!
Don’t do that, just render this.props.children

React stateless functional component to class Component

Can you help me in changing this React stateless functional component to React class based component including the withRouter and history object as given?
const Menu = withRouter(({history}) => (
<AppBar>
</AppBar>
))
export default Menu
class Menu extends React.Component {
render() {
// you can use this.props.history anywhere in the class
const { history } = this.props;
return <AppBar>...</AppBar>
}
}
export default withRouter(Menu);
First, create your class component and then, create a constructor for the class. You can then define the states required inside the constructor, something like this-
export default class Menu extends React.Component {
constructor(props) {
super(props);
this.state = {
SomeVar: xyz,
AnotherVar: undefined
}
}
render() {
return withRouter(({history}) => (
<AppBar> </AppBar>
));
}
}

Update state for component by event handle in other component in different file?

I have two component in my project one is Tag and the other is LandingTicker so i want when i click Tag componet update state for LandTicker componet, and landticker componet in different file.
how i can do that?
thank you.
Tag component code::
tag/index.js
import React from 'react';
import './index.scss';
class Tag extends React.Component {
handleClick(e) {
let tags = document.querySelectorAll('.show-clickable');
Array.from(tags).map(el => el.classList.remove('selected-tag'))
e.target.classList.add('selected-tag');
/*
Here i should update the state for LandingTicker component.
and remember any component in different file.
How i can do that???
*/
}
render() {
return (
<div
className="show-clickable"
onClick={this.handleClick}
>
click here
</div>
);
}
}
export default Tag;
LandingTicker component code::
LandingTicker/index.js
import React from 'react';
import TickerRow from './TickerRow';
import './index.scss';
class LandingTicker extends React.Component {
state = {
coin: 'USD'
}
render() {
return (
<div className="landing-ticker__body">
{selectCoin(this.state.coin)}
</div>
</div>
);
}
}
const selectCoin = (coin) => {
const coins = {
USD: ['BTCUSD', 'ETHUSD', 'EOSUSD', 'LTCUSD'],
EUR: ['BTCEUR', 'ETHEUR', 'EOSEUR'],
GBP: ['BTCGBP', 'EOSGBP'],
JPY: ['BTCJPY', 'ETHJPY'],
};
return (
coins[coin].map(el =>
<TickerRow symbol={el} key={el.toString()} />
)
);
}
export default LandingTicker;
Edit:
my component Hierarchy::
StatusTable
TagsTable
Tag
TickerSearch
LandingTickers
TickersRow
StatusTable component code::
import React from 'react';
import TagsTable from './TagsTable';
import TickerSearch from './TickerSearch';
import LandingTicker from './LandingTicker';
import './StatusTable.scss';
class StatusTable extends React.Component {
render() {
return (
<div className="status-table">
<TagsTable />
<TickerSearch />
<LandingTicker />
</div>
);
}
}
export default StatusTable;
React handle all its component data in the form of state and props(immutable). So it is easy to pass data from parent to child or one component to another using props :
Your Tag.js file:
import React, { Component } from "react";
import LandingTicker from "./LandTicker";
class Tag extends Component {
constructor(props) {
super(props);
this.state = {
trigger: true
};
}
handleClick(e) {
// do all logic here and set state here
this.setState({ trigger: this.state.trigger });
}
render() {
//And then pass this state here as a props
return (
<div className="show-clickable" onClick={this.handleClick}>
click here
<LandingTicker trigger={this.state.trigger} />
</div>
);
}
}
export default Tag;
Inside LandTicker.js file:
import React from 'react';
import TickerRow from './TickerRow';
import './index.scss';
class LandingTicker extends React.Component {
state = {
coin: 'USD'
}
render() {
//Catch your props from parent here
//i.e this.props(it contains all data you sent from parent)
return (
<div className="landing-ticker__body">
{selectCoin(this.state.coin)}
</div>
);
}
}
const selectCoin = (coin) => {
const coins = {
USD: ['BTCUSD', 'ETHUSD', 'EOSUSD', 'LTCUSD'],
EUR: ['BTCEUR', 'ETHEUR', 'EOSEUR'],
GBP: ['BTCGBP', 'EOSGBP'],
JPY: ['BTCJPY', 'ETHJPY'],
};
return (
coins[coin].map(el =>
<TickerRow symbol={el} key={el.toString()} />
)
);
}
export default LandingTicker;
I think this is the best answer for your question if you don't use state management system such as Redux or Mobx.
https://medium.com/#ruthmpardee/passing-data-between-react-components-103ad82ebd17
(you need to check third option)

How can i use a function in different files in React?

I'm trying to use a function, which is in a different component from App.js.
and I'm having the syntax error, I don't know what did I do wrong. I have a button in App.js and when I click on it, that function from another component that I've mentioned earlier should trigger.
app.js:
import React from 'react';
import {shaking} from './components/Tree/Tree.js';
class App extends React.Component {
constructor() {
super();
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
shaking();
console.log("done !");
}
render() {
return (
<div>
<Tree className='tree' />
<Apples />
<Basket />
<br/>
<button className="start-btn" onClick={this.handleClick}>Start !</button>
<br/>
</div>
);
}
};
export default App;
And this is my another component:
import React from 'react';
import TreeSvg from './Tree-svg/TreeSvg.js';
import './Tree.sass';
export function shaking(){
const tree = document.getElemenetsByClassName(".tree-img")[0];
tree.classList.add("apply-shake");
console.log('shaked!');
}
class Tree extends React.Component{
constructor() {
super();
this.shaking = this.shaking.bind(this);
}
shaking() {
this.setState({shaked:'1'});
const tree = document.getElemenetByClassName(".tree-img");
tree.classList.add("apply-shake");
console.log('shaked!');
}
render(){
return(
<div className="tree-img">
<TreeSvg />
</div>
);
}
};
export default Tree;
Make your Tree component like this
import React from 'react';
import TreeSvg from './Tree-svg/TreeSvg.js';
import './Tree.sass';
export function shaking(){
const tree = document.getElementsByClassName(".tree-img")[0];
tree.classList.add("apply-shake");
console.log('shaked!');
}
class Tree extends React.Component{
constructor() {
super();
this.state = {
shaked : ''
}
shaking() {
this.setState({shaked:'1'});
const tree = document.getElementByClassName(".tree-img");
tree.classList.add("apply-shake");
console.log('shaked!');
}
render(){
return(
<div className="tree-img">
<TreeSvg />
</div>
);
}
};
export default Tree;
You do have 2 syntax errors in your code. Both are located at the Tree component file.
At your exported function (Line 6):
const tree = document.getElemenetsByClassName(".tree-img")[0];
replace Elemenets with Elements.
At the class method shaking() (Line 21):
const tree = document.getElemenetByClassName(".tree-img"); replace Elemenet with Element

Categories