React doesn't render unless I add a console.log() instruction - javascript

I have these two React components:
class Record extends React.Component {
render() {
...
return (
<div className="animated slideInUpTiny animation-duration-3">
{
showMessage && currentRecord &&
<Alert />
}
<div className="row">
<CardBox styleName="col-lg-12">
<AttrActions module={this.props.module} app={this.props.app} set={currentCatalog} record={currentRecord} accessCase="controls"/>
<AttrForm
fields_meta={alertedFieldsMeta}
currentForm={this.getCurrentForm()}
originalForm={this.state.originalForm}
reportChange={this.catchChange}
fetchList={fetchList}
hierarchy={this.state.hierarchy}
catalogsList={catalogsList}
fetchRecord={fetchRecord}
searchInCatalog={searchInCatalog}
/>
</CardBox>
</div>
<div className="crud-footer">
<ControlButtons />
</div>
</div>
);
}
}
class AttrActions extends React.Component {
render() {
console.log(this.props);
switch (this.props.module) {
case 'Inventory': {
return (
<InventoryActions {...this.props} />
);
}
default: {
return null;
}
}
}
}
The problem is that component AttrActions is never rendered unless I add a console.log() instruction in component Record, like this:
return (
<div className="animated slideInUpTiny animation-duration-3">
{
showMessage && currentRecord &&
<Alert />
}
<div className="row">
<CardBox styleName="col-lg-12">
{console.log('here')}
<AttrActions module={this.props.module} app={this.props.app} set={currentCatalog} record={currentRecord} accessCase="controls"/>
<AttrForm
fields_meta={alertedFieldsMeta}
currentForm={this.getCurrentForm()}
originalForm={this.state.originalForm}
reportChange={this.catchChange}
fetchList={fetchList}
hierarchy={this.state.hierarchy}
catalogsList={catalogsList}
fetchRecord={fetchRecord}
searchInCatalog={searchInCatalog}
/>
</CardBox>
</div>
<div className="crud-footer">
<ControlButtons />
</div>
</div>
);
Only in this case, I get the console.log(this.props) in the console. If I don't add this instruction, component AttrActions is never rendered.
EDIT
I found that when I put each component on different CardBox, the problem disappears, but I would like them both to be contained together:
return (
<div className="animated slideInUpTiny animation-duration-3">
{
showMessage && currentRecord &&
<Alert />
}
<div className="row">
<CardBox styleName="col-lg-12">
<AttrActions module={this.props.module} app={this.props.app} set={currentCatalog.name} record={currentRecord} accessCase="controls"/>
</CardBox>
<CardBox styleName="col-lg-12">
<AttrForm
fields_meta={alertedFieldsMeta}
currentForm={this.getCurrentForm()}
originalForm={this.state.originalForm}
reportChange={this.catchChange}
fetchList={fetchList}
hierarchy={this.state.hierarchy}
catalogsList={catalogsList}
fetchRecord={fetchRecord}
searchInCatalog={searchInCatalog}
/>
</CardBox>
</div>
<div className="crud-footer">
<ControlButtons />
</div>
</div>
);

Related

TypeError: instance.render is not a function in React

Hello good evening devs my problem is the following react when trying to load my application gives me the following error
Error React
import React from 'react';
import { Card, CardImg, CardText, CardBody, CardTitle } from 'reactstrap';
class DishDetail extends React.Component {
constructor(props) {
super(props);
this.state = {
}
}
renderDish(dish) {
if(dish != null) {
return (
<Card>
<CardImg top src={dish.image} alt={dish.name} />
<CardBody>
<CardTitle>{dish.name}</CardTitle>
<CardText>{dish.description}</CardText>
</CardBody>
</Card>
);
}
else {
return (
<div></div>
);
}
}
renderComments(dish) {
if (dish.comments != null) {
const comments = this.props.dish.comments.map(review => (
<div key={review.id}>
<ul className="list-unstyled">
{comments}
<li className="list-item">{review.comment}</li>
<li className="list-item">{review.author}</li>
<li className="list-item">{review.date}</li>
</ul>
</div>
));
}
else {
return (
<div></div>
);
}
return (
<div className="row">
<div className="col-12 col-md-5 m-1">
{this.renderDish(this.props.selectedDish)}
</div>
<div className="col-12 col-md-5 m-1">
<h4>comments</h4>
</div>
</div>
)
}
}
export default DishDetail;
I have made several changes to the code I am using the ES6 syntax, I would appreciate your help as I am trying to render from one component to another
The problem is in react class component you need to use render function to return the jsx you want to render if the last return is something you want to render then do it like this:
import React from 'react';
import { Card, CardImg, CardText, CardBody, CardTitle } from 'reactstrap';
class DishDetail extends React.Component {
constructor(props) {
super(props);
this.state = {
}
}
renderDish(dish) {
if(dish != null) {
return (
<Card>
<CardImg top src={dish.image} alt={dish.name} />
<CardBody>
<CardTitle>{dish.name}</CardTitle>
<CardText>{dish.description}</CardText>
</CardBody>
</Card>
);
}
else {
return (
<div></div>
);
}
}
renderComments(dish) {
if (dish.comments != null) {
const comments = this.props.dish.comments.map(review => (
<div key={review.id}>
<ul className="list-unstyled">
{comments}
<li className="list-item">{review.comment}</li>
<li className="list-item">{review.author}</li>
<li className="list-item">{review.date}</li>
</ul>
</div>
));
}
else {
return (
<div></div>
);
}
}
render(){
return (
<div className="row">
<div className="col-12 col-md-5 m-1">
{this.renderDish(this.props.selectedDish)}
</div>
<div className="col-12 col-md-5 m-1">
<h4>comments</h4>
<div>{this.renderComments(this.props.selectedDish)}</div>
</div>
</div>
)}
}
export default DishDetail;

How to add className to component based on state without removing initial className

I have a component that is toggleable:
class HamburgerMenu extends React.Component {
constructor(props){
super(props)
this.state = {
toggle: false,
}
}
Toggle() {
this.setState((currentState) => ({
toggle: !currentState.toggle
}));
}
render() {
return (
<StyledHamburgerMenu className="HamburgerMenu" onClick={ () => this.Toggle() }>
<FontAwesomeIcon icon="bars" />
</StyledHamburgerMenu>
)
}
}
and I want to add a class name to a div (extended-right-bar) jsx element in a separate file:
function App() {
return (
<div className="App">
<div className="grid-display">
<div className="right-bar">
<HamburgerMenu />
<PlusButton />
</div>
<div className="extended-right-bar">
<h1 className="main-title">Notes</h1>
<div className="folders-section">
<h2>Folders</h2>
<Folder name="folder" />
<Folder name="folder" />
<Folder name="folder" />
<Folder name="folder" />
</div>
<div className="tags-section">
<h2>Tags</h2>
<Label name="buisness" />
<Label name="buisness" />
<Label name="buisness" />
</div>
</div>
<div className="main">
<NoteWindow />
</div>
</div>
</div>
);
}
How can I do that? They're imported and exported to each other
You can use
element.classList.add("className");
to add a class without overwriting the existing ones.
Replace element and className accordingly
You can use redux to pass classValue on toggle to the different component.
const Component = (props) => {
const className = props.classValue ? "extended-right-bar " + props.classValue : "extended-right-bar";
return (
<div className={customProps.className}>
<h1 className="main-title">Notes</h1>
<div className="folders-section">
<h2>Folders</h2>
<Folder name="folder" />
<Folder name="folder" />
<Folder name="folder" />
<Folder name="folder" />
</div>
</div>;
);
}

How can I display array of data in specific div id by click in a button?

I create a component of react. and there one array with some values. so I need to display that value or data in any specific div by clicking in a button.
this is my array in component.
constructor(){
super()
this.state = {
notificaion: [
"Notification-1",
"Notification-3",
"Notification-4",
"Notification-5",
]
}
}
this is my button with click event.
<button onClick={this.getNotification}>{this.state.notificaion.length}</button>
this is the function that I have create. and to push data in specific div.
getNotification = () =>{
return(
this.state.notificaion.map(items =>(
<li key={items}>{items}</li>
))
)
}
here I want to display when buttons is clicked
<strong>{this.getNotification()}</strong>
This is my full code that I have been tried.
import React, {Component} from 'react';
class Menu2 extends Component{
constructor(){
super()
this.state = {
notificaion: [
"Notification-1",
"Notification-3",
"Notification-4",
"Notification-5",
]
}
}
getNotification = () =>{
return(
this.state.notificaion.map(items =>(
<li key={items}>{items}</li>
))
)
}
render(){
return(
<div className="header">
<div className="container">
<div className="row">
<div className="col-lg-12 col-sm-12 col-xs-12">
<div className="text-center mb-20">
<h1>Notificaion Status</h1>
<p>Check notificatin read/unread</p>
</div>
</div>
</div>
<div className="row">
<div className="col-lg-12 col-sm-12 col-xs-12">
<div className="card border-dark mb-3">
<div className="card-body text-dark">
<p className="card-text" style={{textAlign: 'center'}}>
{this.state.notificaion.length > 0
?
<span>You Have <button onClick={this.getNotification}>{this.state.notificaion.length}</button> Unread Notifications</span>
:
<span>You Have <button onClick={this.getNotification}>{this.state.notificaion.length}</button> Unread Notifications}</span>}
</p>
<strong>{this.getNotification()}</strong>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default Menu2;
import React, { Component } from 'react';
class App extends Component {
constructor(props) {
super(props);
this.state = {
notificaion: [
"Notification-1",
"Notification-3",
"Notification-4",
"Notification-5",
],
notificationHtml: ""
}
}
getNotification = () => {
this.setState({
notificationHtml: this.state.notificaion.map(items => (
<li key={items}>{items}</li>
))
});
}
render() {
return (
<div className="App">
<button onClick={this.getNotification}>{this.state.notificaion.length}</button>
<div>
{this.state.notificationHtml}
</div>
</div>
);
}
}
export default App;
I would implemented as such:
this.state = {
visible: false,
notifications: ...
}
toggleVisibility() =>{
this.setState({
visibile: true
})
}
Don't forget to bind the "toggleVisibility" function. Then
in your component:
<button onClick={this.toggleVisibility}/>
...
{if(this.state.visible){
<strong>this.state.notifications.map(notification,i) =>
<li key={i}>{notification}</li>
</strong>
}
You can add a property showNotification in state. And based on the value of it, we can show the notification.
Also add a method showNotificationHandler that toggles the showNotification value.
class Menu2 extends Component {
constructor() {
super();
this.state = {
notificaion: [
"Notification-1",
"Notification-3",
"Notification-4",
"Notification-5"
],
// adding a property "showNotification"
showNotification: false
};
}
getNotification = () => {
return this.state.notificaion.map(items => <li key={items}>{items}</li>);
};
// method that toggles the "showNotification" value
showNotificationHandler = () => {
this.setState(({ showNotification }) => ({
showNotification: !showNotification
}));
};
render() {
return (
<div className="header">
<div className="container">
<div className="row">
<div className="col-lg-12 col-sm-12 col-xs-12">
<div className="text-center mb-20">
<h1>Notificaion Status</h1>
<p>Check notificatin read/unread</p>
</div>
</div>
</div>
<div className="row">
<div className="col-lg-12 col-sm-12 col-xs-12">
<div className="card border-dark mb-3">
<div className="card-body text-dark">
<p className="card-text" style={{ textAlign: "center" }}>
{this.state.notificaion.length > 0 ? (
<span>
You Have{" "}
<button onClick={this.showNotificationHandler}>
{this.state.notificaion.length}
</button>{" "}
Unread Notifications
</span>
) : (
<span>
You Have{" "}
<button onClick={this.showNotificationHandler}>
{this.state.notificaion.length}
</button>{" "}
Unread Notifications}
</span>
)}
</p>
<strong>
// Depending on the value of "showNotification" we get notification
// if "showNotification" is true then get the notification
{this.state.showNotification && this.getNotification()}
</strong>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default Menu2;

Passing props.children to a conditionally rendered component

I have Product component that renders a modal component based on a showModal boolean value in the Product component state. This is the render method in Product
render() {
const { .... } = this.props.data;
return (
<>
{this.state.showModal && (
<Modal
product={this.props.data}
toggleModal={this.onToggleModal}
addToCart={this.props.onAddToCart}
/>
)}
<li className="product-body">
<img
src=".."
onClick={this.onToggleModal}
/>
<h2>{...}</h2>
<h3>{..}</h3>
<h3>{..}</h3>
<h2 className="product-price">{...}</h2>
<button type="button" onClick={this.props.onAddToCart}>
Buy now
</button>
</li>
</>
);
}
I want to pass down the content inside li to the Modal.How can I make use of props.children in this case for the Modal component, so I dont have to pass down the data to be displayed as props ?
If Modal is another component then you can pass the list as
render() {
const { .... } = this.props.data;
return (
<>
{this.state.showModal && (
<Modal
product={this.props.data}
toggleModal={this.onToggleModal}
addToCart={this.props.onAddToCart}
>
<ListItems {...this.props}/>
</Modal>
)}
<ListItems {...this.props}/>
</>
);
}
Let the ListItems be a separate component as
class ListItems extends React.Component {
render() {
return(
<li className="product-body">
<img
src=".."
onClick={this.onToggleModal}
/>
<h2>{...}</h2>
<h3>{..}</h3>
<h3>{..}</h3>
<h2 className="product-price">{...}</h2>
<button type="button" onClick={this.props.onAddToCart}>
Buy now
</button>
</li>
)}
}
class ListItems extends React.Component {
render(){
return(
<li className="product-body">
<img
src=".."
onClick={this.onToggleModal}
/>
<h2>{...}</h2>
<h3>{..}</h3>
<h3>{..}</h3>
<h2 className="product-price">{...}</h2>
<button type="button" onClick={this.props.onAddToCart}>
Buy now
</button>
</li>
)
}
}
class Wrapper extends React.Component {
render(){
return (
<Modal
product={this.props.data}
toggleModal={this.onToggleModal}
addToCart={this.props.onAddToCart}
>
<ListItems />
</Modal>
)
}
}
class Modal extends React.Component {
render(){
return (
<div>
<h1>Modal Title</h1>
<div>{this.props.children}</div>
</div>
)
}
}

React - How to show component from an image onClick event in another component?

I have 3 React components:
-Home - need to display the component here when image is
clicked from the Header component
-Header- Contains the image tag that will be clicked to
show the AllSites Component.
-AllSites - component that needs displayed in Home component when Image is
clicked in the Header component.
Header
export class Header extends React.Component<any, any> {
private readonly searchServerUrl = "";
private appButtonElement: HTMLElement;
constructor(props: any) {
super(props);
this.state = { showAppMenu: false };
}
render() {
const { showAppMenu } = this.state;
const { className, navItems, singleColumn, appItems } = this.props;
return (
<header className={className}>
<div className="app-icon">
<button className="nav-button" onClick={() => this.toggleAppMenu()} ref={(menuButton: any) => this.appButtonElement = menuButton}><i className="ms-Icon ms-Icon--Waffle" aria-hidden="true"></i></button>
</div>
***When image is clicked, show the <AllSites/> component in the HomeComponent below.***
<img src="/Styles/Images/logo/loop-logo-white.png" className="nav-logo" onClick={} />
{showAppMenu ? <ApplicationMenu navItems={appItems} targetElement={this.appButtonElement} onDismiss={() => this.onDismiss()} /> : null}
<div className="nav-container"><TopNavigation classNam
e={className} navItems={navItems} singleColumn={singleColumn} /></div>
<div className="search-container">
<SearchBox onSearch={(searchTerm: string) => this.executeSearch(searchTerm)} />
</div>
</header>
);
}
Home
export class HomeComponent extends React.Component<any, any> {
constructor(props: any) {
super(props);
this.state = { navItems: [], appItems: [], singleColumnLayout: false, showAllSites: false };
}
componentDidMount() {
this.checkWidth();
window.addEventListener("resize", this.checkWidth.bind(this));
this.fetchNavigation()
.then(nav => this.setState({ navItems: nav }));
this.fetchAppIcons()
.then(icons => this.setState({ appItems: icons }));
}
componentWillUnmount(): void {
window.addEventListener("resize", this.checkWidth.bind(this));
}
render() {
const { navItems, appItems, singleColumnLayout } = this.state;
return (
<Fabric>
<Header navItems={navItems} appItems={appItems} singleColumn={singleColumnLayout} />
<div className="main-container">
<AlertBar />
<div className="main-content">
<div className="ms-Grid">
When the image tag is clicked, I need to render the <AllSites/> component here
<Hero singleColumn={singleColumnLayout} />
<div className="ms-Grid-row">
<div className="ms-Grid-col ms-sm12 ms-xl4 webpart-container">
<UpcomingEvents />
</div>
<div className="ms-Grid-col ms-sm12 ms-xl4 webpart-container">
<EmployeeNews />
</div>
<div className="ms-Grid-col ms-sm12 ms-xl4 webpart-container">
<div className="ms-Grid-row">
<div className="ms-Grid-col ms-sm12 webpart-container">
<IndustryNews />
</div>
<div className="ms-Grid-col ms-sm12 webpart-container">
<Quote />
</div>
</div>
</div>
</div>
</div>
<Footer navItems={navItems} />
</div>
</div>
</Fabric>
);
}
In the simplest approach you will need a common parent component for your Home and Header that will hold some shared state for them and that will pass a callback to update this state as a prop to Header. In the shared state you need a flag that will be responsible for showing/hiding AllSites component, this flag you will pass as a prop to Home.
You can see a basic example here
If you need a more advanced state management solution, you can check redux library

Categories

Resources