I am currently trying to integrate Patternfly React in my project. This is the link im using for reference which is working fine. But need to have separate component for header , footer , topnav and sidenav. So while partitioning the code in to components im getting issue as
Invalid prop nav supplied to PageSidebar, expected a ReactNode.
Here is my Sidenav Code
import ReactDOM from 'react-dom';
import "#patternfly/react-core/dist/styles/base.css";
import '../../app/fonts.css';
import React from 'react';
import {
Nav,
NavExpandable,
NavItem,
NavList
} from '#patternfly/react-core';
function SideNav() {
this.state = {
activeGroup: 'grp-1',
activeItem: 'grp-1_itm-1'
};
this.onNavSelect = result => {
this.setState({
activeItem: result.itemId,
activeGroup: result.groupId
});
};
const { activeItem, activeGroup } = this.state;
const PageNav = (
<Nav onSelect={this.onNavSelect} aria-label="Nav" theme="dark">
<NavList>
<NavExpandable title="System Panel" groupId="grp-1" isActive={activeGroup === 'grp-1'} isExpanded>
<NavItem groupId="grp-1" itemId="grp-1_itm-1" isActive={activeItem === 'grp-1_itm-1'}>
Overview
</NavItem>
<NavItem groupId="grp-1" itemId="grp-1_itm-2" isActive={activeItem === 'grp-1_itm-2'}>
Resource usage
</NavItem>
<NavItem groupId="grp-1" itemId="grp-1_itm-3" isActive={activeItem === 'grp-1_itm-3'}>
Hypervisors
</NavItem>
</NavExpandable>
</NavList>
</Nav>
);
return (PageNav);
}
export default SideNav;
The above is my sideNav function component and using it in my layout component.
My Header component
import "#patternfly/react-core/dist/styles/base.css";
import '../../app/fonts.css';
import React from 'react';
import {
Page,
PageHeader,
PageSection,
PageSectionVariants,
PageSidebar,
TextContent,
Text,
} from '#patternfly/react-core';
import SideNav from '../sideNav/sideNav';
class Layout extends React.Component {
render() {
const Header = (
<PageHeader
toolbar={PageToolbar}
showNavToggle
/>
);
const Sidebar = <PageSidebar nav={SideNav} theme="dark" />;
return (
<React.Fragment>
<Page
header={Header}
sidebar={Sidebar}
mainContainerId={pageId}
>
<PageSection variant={PageSectionVariants.light}>
<TextContent>
<Text component="h1">Main title</Text>
<Text component="p">
Body
</Text>
</TextContent>
</PageSection>
</Page>
</React.Fragment>
);
}
}
export default Layout;
The issue is when passing my function component to Patternfly's PageSidebar component in nav attribute as
const Sidebar = <PageSidebar nav={SideNav} theme="dark" />; .
What exactly is wrong with this?
Looking at the code in the seed app, the nav property of <PageSidebar> is set to some React elements (some JSX), and not to a React component (a function returning some JSX).
I guess that instead of using nav={Sidenav}, you should use nav={<Sidenav />}, to make your code match the example.
Related
I am using React in Laravel and I found a problem that I can't refresh or reload a page in React. So to solve this problem I found many suggestions like use historyApiFallback, 404 page and many other ways But I found none of them useful to me now.
I know I can't do this because React has no system for it because of server- and client-side routing. Then i found a demo project where they used Redux and I can refresh their page. I got the demo project where i can use any component and refresh them how many times I want. So there is a file name with Base.js and I am not understanding this file why he used it what is doing. Let me share the file and where it was used.
Base.js
import React from 'react';
import { connect } from 'react-redux';
import Header from './components/Header';
const Base = ({ children }) => (
<div>
<Header />
<main>{children}</main>
</div>
);
const mapStateToProps = (state) => ({
isAuthenticated: state.Auth.isAuthenticated,
});
export default connect(mapStateToProps)(Base);
Header.Js
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
import {
Nav,
NavItem,
NavLink,
UncontrolledDropdown,
DropdownToggle,
DropdownMenu,
DropdownItem,
} from 'reactstrap';
import * as actions from '../store/actions';
class Header extends Component {
handleLogout = (e) => {
e.preventDefault();
this.props.dispatch(actions.authLogout());
};
render() {
return (
<header className="d-flex align-items-center justify-content-between">
<h1 className="logo my-0 font-weight-normal h4">
<Link to="/">Laravel React</Link>
</h1>
{this.props.isAuthenticated && (
<div className="navigation d-flex justify-content-end">
<Nav>
<NavItem>
<NavLink tag={Link} to="/archive">
Archive
</NavLink>
<NavLink tag={Link} to="/Myfile">
Myfile
</NavLink>
</NavItem>
<UncontrolledDropdown nav inNavbar>
<DropdownToggle nav caret>
Account
</DropdownToggle>
<DropdownMenu right>
<DropdownItem>Settings</DropdownItem>
<DropdownItem divider />
<DropdownItem onClick={this.handleLogout}>
Log Out
</DropdownItem>
</DropdownMenu>
</UncontrolledDropdown>
</Nav>
</div>
)}
</header>
);
}
}
const mapStateToProps = (state) => ({
isAuthenticated: state.Auth.isAuthenticated,
});
export default connect(mapStateToProps)(Header);
Public.js
import PropTypes from 'prop-types';
import { Route } from 'react-router';
import Base from '../Base';
const PublicRoute = ({ component: Component, ...rest }) => (
<Route
{...rest}
render={(props) => (
<Base>
<Component {...props} />
</Base>
)}
/>
);
PublicRoute.propTypes = {};
export default PublicRoute;
split.js
import React from 'react';
import PropTypes from 'prop-types';
import { Route } from 'react-router';
import { connect } from 'react-redux';
import Base from '../Base';
const SplitRoute = ({
component: Component,
fallback: Fallback,
isAuthenticated,
...rest
}) => (
<Route
{...rest}
render={(props) => (isAuthenticated ? (
<Base>
<Component {...props} />
</Base>
) : (
<Base>
< Fallback {...props} />
</Base>
))}
/>
);
SplitRoute.propTypes = {
isAuthenticated: PropTypes.bool.isRequired,
};
const mapStateToProps = (state) => ({
isAuthenticated: state.Auth.isAuthenticated,
});
export default connect(mapStateToProps)(SplitRoute);
Now it has authenticated system so I understand it but why it is using base function and what it is doing? I am not understanding.
What it looks like is that the Base.js is a container for the Header and any rendered children (passed props). This is a good practise in react to separate logic and make it more readable. So when he imports Base into the Public.js file, it will render the Header and the component he is passing to it from the public function props.
Think of it like the skeleton of the layout, by importing Base it will always render the header and any logic inside of the header file, and whatever he is passing down to it. As you can see he is passing different components to it depending on whether isAuthenticated is true or false. If it is false, they are rendering Base and passing a fallback component - this will render inside of the main tag within the Base function.
Still learning React to the best of my ability so forgive me if this code isn't the most logical.
I have made a reusable CustomButton component in React to use across my app. I've then created 3 Card components on a Welcome page with each Card nesting this CustomButton inside of it, with each CustomButton using Link from react-router to navigate to different pages of the app. For the 3rd card, I would like to have this button disabled as this particular page will be 'coming soon'. I've been able to add a className to Link within props of the last Card to set the opacity of the text to look inactive, but want to be able to customise the entire button (not just the text within) to make it look greyed out etc.
Is there a simple way to do this?
This is my code so far:
Card:
import React, { useState } from 'react';
import { Card } from 'react-bootstrap';
import CustomButton from './CustomButton';
const WelcomeCard = (props) => {
return (
<>
<Card className='m-3 p-2 welcome-card rounded'>
<Card.Body className='welcome-card__body'>
<Card.Text>{props.text}</Card.Text>
<CustomButton link={props.link} />
</Card.Body>
</Card>
</>
);
};
export default WelcomeCard;
CustomButton:
import React from 'react';
const CustomButton = (props) => {
return <button className='custom-button'>{props.link}</button>;
};
export default CustomButton;
WelcomeScreen - The last component at the bottom is where I want to disable this CustomButton:
import React, { useState } from 'react';
import { Row, Col } from 'react-bootstrap';
import WelcomeCard from '../components/WelcomeCard';
import Loader from '../components/Loader';
import { Link } from 'react-router-dom';
const WelcomeScreen = () => {
const [loading, setLoading] = useState(false);
return (
<>
<div class='welcome-container'>
<div>
<h1 className='p-2 my-3 welcome-header'>Welcome</h1>
</div>
<div className='cards-container'>
<Row>
<Col>
<WelcomeCard
link={
<Link className='cards-link' to='/company'>
Company
</Link>
}
/>
</Col>
<Col>
<WelcomeCard
link={
<Link className='cards-link' to='/landscape'>
Landscape
</Link>
}
/>
</Col>
<Col>
<WelcomeCard
link={
<Link className='cards-link disabled-link' to='/insights'>
AI Insights
</Link>
}
/>
</Col>
</Row>
</div>
</div>
</>
);
};
export default WelcomeScreen;
Thanks in advance for any guidance!
Why you don't use props to solve this problem?
Edit your CustomButton like this:
import React from 'react';
const CustomButton = (props) => {
if(!props.active) return <button className='custom-button-disabled'></button>;
return <button className='custom-button'>{props.link}</button>;
};
export default CustomButton;
You can pass this prop into the CustomButton Component now like you are doing with the link prop.
I wanted to use "React Bootstrap Hamburger Menu" HamburgerMenu copied the code from there and I get an error errorScreen
"Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
You might have mismatching versions of React and the renderer (such as React DOM)
You might be breaking the Rules of Hooks
You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. "Here is my code
Mobile_Navbar.jsx
import React, { Component } from 'react';
import {
MDBNavbar,
MDBNavbarBrand,
MDBNavbarNav,
MDBNavItem,
MDBNavLink,
MDBNavbarToggler,
MDBCollapse,
MDBContainer
} from 'mdbreact';
import { BrowserRouter as Router } from 'react-router-dom';
class Test extends Component {
state = {
collapseID: ''
};
toggleCollapse = collapseID => () => {
this.setState(prevState => ({
collapseID: prevState.collapseID !== collapseID ? collapseID : ''
}));
};
render() {
return (
<Router>
<MDBContainer>
<MDBNavbar
color='light-blue lighten-4'
style={{ marginTop: '20px' }}
light
>
<MDBContainer>
<MDBNavbarBrand>Navbar</MDBNavbarBrand>
<MDBNavbarToggler
onClick={this.toggleCollapse('navbarCollapse1')}
/>
<MDBCollapse
id='navbarCollapse1'
isOpen={this.state.collapseID}
navbar
>
<MDBNavbarNav left>
<MDBNavItem active>
<MDBNavLink to='#!'>Home</MDBNavLink>
</MDBNavItem>
<MDBNavItem>
<MDBNavLink to='#!'>Link</MDBNavLink>
</MDBNavItem>
<MDBNavItem>
<MDBNavLink to='#!'>Profile</MDBNavLink>
</MDBNavItem>
</MDBNavbarNav>
</MDBCollapse>
</MDBContainer>
</MDBNavbar>
</MDBContainer>
</Router>
);
}
}
export default Test;
App.js
import React from 'react';
import './App.css';
import Test from './components/Mobile_Menu/Mobile_Navbar';
function App(props) {
return (
<div className="App">
<Test />
</div>
);
}
export default App;
It seems there is some kind of problem when we use the mdbootstrap Library MDBNavLink component. I didn't go deep on that to be able to explain why, though.
I solved this problem by importing the Link component from react-router-dom and use it instead with the className='nav-link'.
import { Link } from "react-router-dom";
//Snippet
// [....]
<MDBNavItem>
<Link
className='nav-link'
exact
to='/'
onClick={closeCollapse('mainNavbarCollapse')}
>
Home
</Link>
</MDBNavItem>
// [...]
I'm trying some things in react. I'm rendering the AppBar and the Drawer from v0 Material-UI as functional components. I have added the handleDrawerClick function in the class and sending the function as a props to use as a click function in the functional component. But the click function is not working. The problem here is wrapping up the function as the param and passing it as props might not be working. If there's any other way to achieve the click any help would be appreciated but we need to make sure that we're using the fancy components in the functional components and rendering those in the class just like shown in the Demo. onLeftIconButtonClick, the drawer open and closing needs to get controlled.
I have added one working demo here through stackblitz => Working Demo
Here's my code:
import React, { Component } from 'react';
import { render } from 'react-dom';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import darkBaseTheme from 'material-ui/styles/baseThemes/darkBaseTheme';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import AppBar from 'material-ui/AppBar';
import Drawer from 'material-ui/Drawer';
import MenuItem from 'material-ui/MenuItem';
import './style.css';
export const getMenuBar = (isBarOpened) => {
return(
<Drawer open={isBarOpened}>
<MenuItem>Menu Item</MenuItem>
<MenuItem>Menu Item 2</MenuItem>
</Drawer>
);
}
export const getAppBar = (handleDrawerClick) => {
return(
<AppBar
title="My AppBar"
className="st_appBarClass"
titleStyle={{ color: "#FFFFFF" }}
onLeftIconButtonClick={handleDrawerClick()}
/>
);
}
class App extends Component {
constructor() {
super();
this.state = {
name: 'React',
isMenuOpened: false
};
}
handleDrawerClick = (e) => {
console.log(e);
if(e) {
this.setState({ isMenuOpened: !this.state.isMenuOpened });
}
}
render() {
return (
<MuiThemeProvider muiTheme={getMuiTheme(darkBaseTheme)}>
<div className='product-list-wrapper'>
{/*<ProductList products={products} />*/}
{getAppBar(this.handleDrawerClick)}
{getMenuBar(this.state.isMenuOpened)}
</div>
</MuiThemeProvider>
)
}
}
render(<App />, document.getElementById('root'));
export const getAppBar = (handleDrawerClick) => {
return(
<AppBar
title="My AppBar"
className="st_appBarClass"
titleStyle={{ color: "#FFFFFF" }}
onLeftIconButtonClick={handleDrawerClick} //Remove ()
/>
);
}
To open menu remove unnecessary round brackets
<AppBar
title="My AppBar"
className="st_appBarClass"
titleStyle={{ color: "#FFFFFF" }}
onLeftIconButtonClick={handleDrawerClick}//<---here
/>
To close menu provide an onClick to the parent div
<div onClick={this.handleDrawerClick} className='product-list-wrapper'> //<----here
{/*<ProductList products={products} />*/}
{getAppBar(this.handleDrawerClick)}
{getMenuBar(this.state.isMenuOpened)}
</div>
this is my simple home.js code. None relevant code has been removed.
import Banner from '../components/Banner'
export default function Home() {
return (
<Hero>
<Banner title="luxurious rooms" subtitle="delux rooms starting at $299">
<Link to="/rooms" className="btn-primary">
Our rooms
</Link>
</Banner>
</Hero>
and this my banner.js
import React from 'react'
export default function Banner({childern,title,subtitle}) {
return (
<div className="banner">
<h1>{title}</h1>
<div />>
<p>{subtitle}</p>
{childern}
</div>
)
}
I don't understand why it is not rendering.
In the bedg I contd see <banner>. tag inside of hero.
How can I solve this issue?
Ok, I created a pen for this, but it's not saving so I'll add the code here. It looks like you are taking a difficult approach for a relatively easy concept. When you pass props to a component, you access them within that component using this.props.nameOfProp. You don't need to pass link as a child, just add Link inside the child component, and pass the info you need for the Link as props.
EDIT: Here's a working example https://codesandbox.io/embed/elegant-fast-m52bt
import React from "react";
import ReactDOM from "react-dom";
import Banner from "./Banner";
import { BrowserRouter as Router } from "react-router-dom";
class App extends React.Component {
render() {
return (
<div>
<Banner
title={"luxurious rooms"}
subtitle={"delux rooms starting at $299"}
path={"/rooms"}
classList={"btn-primary"}
/>
</div>
);
}
}
ReactDOM.render(
<Router>
<App />
</Router>,
document.querySelector("#app")
);
Then your banner should look something like this:
import React from "react";
import { Link } from "react-router-dom";
class Banner extends React.Component {
render() {
return (
<div className="banner">
<h1>{this.props.title}</h1>
<p>{this.props.subtitle}</p>
<Link
to={this.props.path}
className={this.props.classList}
>
Link Text (could also be a prop)
</Link>
</div>
);
}
}
export default Banner;