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>
Related
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 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.
I have been trying to use React-paginate library for pagination, however, the buttons formed by it is not clickable,i don't understand what i am doing wrong
And there are no example given, or no question asked
What would be the correct way of using this pagination
Here is the code of my App.js
import React, { Component } from 'react';
import './App.css';
import Navbar from '../src/components/navbar/navbar'
import SearchIt from '../src/components/searchField/search'
import Container from 'react-bootstrap/Container'
import Card from '../src/components/cards/cards'
import Axios from 'axios'
import Pagination from '../src/components/pagination/paginating'
class App extends Component {
state={
fetchedData:[]
}
componentDidMount(){
Axios.get('http://localhost:3000/1').then((responseData)=>{
//console.log(responseData.data)
this.setState({fetchedData:responseData.data})
}).catch((err)=>{
console.log(err)
})
}
handlePageClicked = data => {
let selected = data.selected;
console.log(selected)
};
render() {
return (
<div className="App">
<Navbar/>
<Container>
<SearchIt/>
<Card data={this.state.fetchedData}/>
<Pagination handlePageClick={this.handlePageClicked}/>
</Container>
</div>
);
}
}
export default App;
And here is the code for paginating.js
import React,{Component} from 'react'
import ReactPaginate from 'react-paginate';
import './paginateStyle.css'
const page = (props)=>{
return(
<ReactPaginate
previousLabel={'previous'}
nextLabel={'next'}
breakLabel={'...'}
breakClassName={'break-me'}
pageCount={10}
marginPagesDisplayed={2}
pageRangeDisplayed={5}
onPageChange={props.handlePageClick}
containerClassName={'pagination'}
subContainerClassName={'pages pagination'}
activeClassName={'active'}
/>
)
}
export default page
These button are not clickable
I did a quick sample and it worked.
import ReactPaginate from 'react-paginate';
const Pagination = (props) => {
return (
<ReactPaginate
previousLabel={'previous'}
nextLabel={'next'}
breakLabel={'...'}
breakClassName={'break-me'}
pageCount={10}
marginPagesDisplayed={2}
pageRangeDisplayed={5}
onPageChange={props.handlePageClick}
containerClassName={'pagination'}
subContainerClassName={'pages pagination'}
activeClassName={'active'}
/>
)
}
class App extends Component {
state = {
selectedPage: 0
}
handlePageClicked = data => {
let selected = data.selected;
this.setState({
selectedPage: selected
})
console.log(selected)
};
render() {
return (
<React.Fragment>
<div>You selected: {this.state.selectedPage}</div>
<div className="App">
<Pagination handlePageClick={this.handlePageClicked} />
</div>
</React.Fragment>
);
}
}
There could be something in paginateStyle.css which is making the Pagination not work properly or some other CSS in your application.
EDIT:
From comments, a ui component with higher z index was over them and was not visible/clickable
I try to activate the drawer when a user clicks a menu iten but my solution don't work. Can you help me, please?
Parent
import React, { Component } from 'react';
// Import Appbar
import AppBar from 'material-ui/AppBar';
import Drawer from 'material-ui/Drawer';
import LeftMenu from './Left_menu';
class Header extends Component {
constructor(props) {
super(props);
this.state = {open: false};
}
handleToggle() {
this.setState({open: !this.state.open});
}
handleClose() {
this.setState({open: false});
}
render() {
return(
<div>
<AppBar
title="Log"
onLeftIconButtonTouchTap={this.handleToggle.bind(this)}
/>
<Drawer
docked={false}
open={this.state.open}
onRequestChange={(open) => this.setState({open})}
>
<LeftMenu handleClose={this.handleClose} />
</Drawer>
</div>
);
}
};
export default Header;
Child
import React, { Component } from 'react';
import Drawer from 'material-ui/Drawer';
import MenuItem from 'material-ui/MenuItem';
class LeftMenu extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<MenuItem onTouchTap={(event) => this.props.handleClose(event)}>Menu Item</MenuItem>
<MenuItem onTouchTap={(event) => this.props.handleClose(event)}>Menu Item 2</MenuItem>
</div>
);
}
}
export default LeftMenu;
I receive a message: TypeError: this.setState is not a function
I'm using Meteor + React + MaterialUI
Thanks
You shouldn't setState in render, take that logic out of onRequestChange, just like you have done with handleToggle and handleClose:
<Drawer
docked={false}
open={this.state.open}
onRequestChange={(open) => this.setState({open})} // this.handleRequest??
>
Solved.
In Parent
<LeftMenu handleClose={this.handleClose.bind(this)} />
In Child
<MenuItem onTouchTap={this.props.handleClose}>Menu Item</MenuItem>
<MenuItem onTouchTap={this.props.handleClose}>Menu Item 2</MenuItem>
Thanks anyway.
I hope, that you can help me with my problem. I can't understand, why property rightIconButton in my example of <ListItem> doesn't work (Material UI component).
<List>
import React from 'react';
import { List } from 'material-ui';
import UsersItem from './UsersItem';
class UsersList extends React.Component {
render() {
return <List>
{this.props.users.map(user => {
return <UsersItem key={user.id} deleteUser={this.props.deleteUser}
user={user}/>
})}
</List>;
}
}
export default UsersList;
<ListItem>
import React from 'react';
import { ListItem, IconButton, Avatar, FontIcon } from 'material-ui';
class UsersItem extends React.Component {
constructor() {
super();
this.deleteUser = this.deleteUser.bind(this);
}
deleteUser(e) {
this.props.deleteUser(this.props.user.id);
e.stopPropagation();
}
render() {
let deleteButton = <IconButton iconClassName="icomoon-icon-delete"
onClick={this.deleteUser}>
</IconButton>;
return <ListItem className="user-item" secondaryText={this.props.user.description}
leftAvatar={<Avatar src="./web/images/avatar.jpg" />}
rightIconButton={deleteButton} secondaryTextLines={2}>
tt { this.props.user.name }
</ListItem>
}
}
export default UsersItem;
Font icon is correct and if I place it on <Toolbar>, it render correct. But it doesn't render in property rightIconButton. I tried SVG icon too from source code on official site of MaterialUI.
Screenshot of result site page (to small reputation for third link) https://github.com/jestonedev/Auction/blob/master/issue.png
What I doing incorrect? Why rightIconButton doesn't work?
In deleteButton > onClick, you are missing to bind this context:
onClick={this.deleteUser.bind(this)}
This is necessary when using the es6 class syntax.