I've been trying to work with this since yesterday, tried different methods and none actually worked. I'm currently using a drawer navigator, tab navigator and I want to open a different scene when clicking a icon.
Here is the current design:
The icon I want to open a new scene is the "filter" up on the top-right corner.
My current header code is:
<Header>
<Left>
<Icon name='ios-menu' style={{ color: 'white' }} onPress={() =>
this.props.navigation.dispatch(DrawerActions.openDrawer())} />
</Left>
<View style={{ width: Dimensions.get('window').width * 0.7 }}>
<Text style={styles.headerTextTop}>Estabelecimentos</Text>
</View>
<Right>
<Icon name='ios-search' style={{ paddingRight: 20, color: 'white' }} />
<Icon name='ios-options' style={{ color: 'white' }} onPress={this.openFilter} />
</Right>
</Header>
and here is the function openFilter:
openFilter = () =>
{
this.props.navigation.navigate('Filter');
}
I'm importing the filter component from its .js file, I can't get it to switch scenes.
Here is the Filter.js (which i'm importing as import Filter from './Filter'):
import React, { Component } from "react";
import {
View,
Text,
Dimensions
} from "react-native";
import { Icon, Header, Left, Right } from 'native-base'
class Filter extends Component {
render() {
return (
<View>
<Header>
<Left>
<Icon name='ios-arrow-back' style={{color: 'white'}} onPress={() =>
this.props.navigation.goBack()} />
</Left>
<View style={{ width: Dimensions.get('window').width * 0.7 }}>
<Text style={sty.headerTextTop}>Filtro</Text>
</View>
<Right>
</Right>
</Header>
</View>
);
}
}
export default Filter;
--EDIT:--
As #Pritish Vaidya suggested, I should implement a Stack Navigator, so I made one:
import { StackNavigator} from 'react-navigation'
import Filter from './Filter';
import App from './App';
import Home from './Home';
const stackNav = StackNavigator({
App: {
screen: App,
navigationOptions:({navigation}) => ({
title: "Main",
headerStyle: { paddingRight: 10, paddingLeft: 10 }
})
},
Filter: {
screen: Filter,
navigationOptions: (props) => ({
title: "Filtro",
})
},
Home: {
screen: Home,
navigationOptions: (props) => ({
title: "Home",
})
}
})
export default stackNav;
But in Home.js when I call navigate using:
<Icon name='ios-options' style={{ color: 'white' }} onPress={() => this.props.navigator.navigate("Filter")} />
It gets me this error:
Related
I'm working on a website where users can read book. In this, homepage showcase multiple books but I want this page to change the size of book cover depending upon display size and not crop them.
I'm also using mui library for creating ui elements.
Home.js
import { ImageList, ImageListItem, ImageListItemBar,
Typography, Link, Grid, Divider } from '#mui/material'
import { useContext } from 'react'
import { useNavigate } from 'react-router-dom'
import { PageLayout, Context } from '../Components/PageLayout'
function Feed({ catg, catgTitle, routeName = "" }) {
const navg = useNavigate();
const bookCatg = useContext(Context)[0][catg];
return (
<>
<Grid
container
direction="row"
justifyContent="space-between"
alignItems="center"
>
<Grid item>
<Typography variant="h6">{catgTitle}</Typography>
</Grid>
<Grid item>
<Link
href={`/book/${routeName}`}
variant="body1"
underline="none"
component="button"
>
More..
</Link>
</Grid>
</Grid>
<Divider />
<ImageList
sx={{ pt: '10px' }}
cols={4}
spacing={1}
rowHeight={250}
>
{bookCatg.map((book) => (
<ImageListItem key={book._id}>
<img
onClick={() => navg(`/book/${book._id}`)}
src={book.img}
sx={{ height: "50px" }}
alt='Not Found'
loading="lazy"
/>
<ImageListItemBar
onClick={() => navg(`/book/${book._id}`)}
sx={{ width: '10vw' }}
title={book.title}
position="below"
/>
</ImageListItem>
))}
</ImageList>
</>
)
}
export default function Home(){
var element = <>
<Feed catgTitle={'New Arrival'}
catg={'newArrival'} routeName={'newest'} />
<Feed catgTitle={'Popular Books'}
catg={'popRating'} routeName={'popular'} />
<Feed catgTitle={'Hot Rated'}
catg={'hotRating'} routeName={'hot'} />
<Feed catgTitle={'Rank'}
catg={'ranking'} routeName={'ranking'} />
</>;
return (
<PageLayout
url="/book"
gridElem={element}
failureMsg="Error"
/>
)
}
PageLayout.jsx
import { Grid, Typography } from '#mui/material'
import { useState, useEffect, createContext } from 'react'
import axios from 'axios'
import Navbar from './Navbar'
import AppFormNav from './AppFormNav'
import Loading from './Loading'
export const Context = createContext({});
export function PageLayout({ url, nav='normal', elem, gridElem, failureMsg }){
const NavType = {
'normal': <Navbar />,
'form': <AppFormNav />
};
const [info, setInfo] = useState({});
const fetchData = async() => {
axios.get(url)
.then((resp) => {
if(resp.status === 200)
setInfo({status: 200, data: resp.data.data});
else if(resp.status === 204)
setInfo({ status: 204, data: resp.message });
})
.catch((err) => {
setInfo({ status: 400, data: err.response.data.data })
// console.log("Bad Request", err.resp.status);
})
};
useEffect(() => {
fetchData();
}, []);
var gridElement = <Loading />, element, message;
if(info.status === 200){
gridElement = gridElem;
element = elem;
}
else if (info.status === 204){
gridElement=<></>;
message = failureMsg ? failureMsg : info.data;
}
return (
<Context.Provider value={info?.data}>
<Grid container sx={{ justifyContent: 'center' }}>
<Grid item> { NavType[nav] } </Grid>
<Grid item xs={12}> { element } </Grid>
<Grid item xs={10}>
<Typography sx={{ justifyContent: "center", alignItems: "center" }}> {message} </Typography>
</Grid>
<Grid item xs={ 10 }> { gridElement } </Grid>
</Grid>
</Context.Provider>
)
}
current look
As you can see the bookcover of different size take up space of other book cover.
Home.jsx
import { ImageList, ImageListItem, ImageListItemBar,
Typography, Link, Grid, Divider } from '#mui/material'
import { useContext } from 'react'
import { useNavigate } from 'react-router-dom'
import { PageLayout, Context } from '../Components/PageLayout'
function Feed({ catg, catgTitle, routeName = "" }) {
const navg = useNavigate();
const bookCatg = useContext(Context)[0][catg];
return (
<>
<Grid
container
direction="row"
justifyContent="space-between"
alignItems="center"
>
<Grid item>
<Typography variant="h6">{catgTitle}</Typography>
</Grid>
<Grid item>
<Link
href={`/book/${routeName}`}
variant="body1"
underline="none"
component="button"
>
More..
</Link>
</Grid>
</Grid>
<Divider />
<ImageList
sx={{ pt: '10px' }}
cols={4}
spacing={1}
// rowHeight={250}
>
{bookCatg.map((book) => (
<ImageListItem key={book._id}>
<img
onClick={() => navg(`/book/${book._id}`)}
src={book.img}
//changed start from here
style={{ aspectRatio: "0.8", resize: "auto", objectFit: "scale-down" }}
//change end here
alt='Not Found'
loading="lazy"
/>
<ImageListItemBar
onClick={() => navg(`/book/${book._id}`)}
sx={{ width: '10vw' }}
title={book.title}
position="below"
/>
</ImageListItem>
))}
</ImageList>
</>
)
}
export default function Home(){
var element = <>
<Feed catgTitle={'New Arrival'}
catg={'newArrival'} routeName={'newest'} />
<Feed catgTitle={'Popular Books'}
catg={'popRating'} routeName={'popular'} />
<Feed catgTitle={'Hot Rated'}
catg={'hotRating'} routeName={'hot'} />
<Feed catgTitle={'Rank'}
catg={'ranking'} routeName={'ranking'} />
</>;
return (
<PageLayout
url="/book"
gridElem={element}
failureMsg="Error"
/>
)
}
just added this style to img tag
style={{ aspectRatio: "0.8", resize: "auto", objectFit: "scale-down"
}}
I am trying to redirect the user if he/she has not logged in. I am using the below snipet to do that.
if(!this.props.isAuthenticated){
this.nextPath('/account/login')
}
But when I execute it, I am getting an error. (Error: Maximum update depth exceeded). If I takeoff the above snippet. I am not getting Error.
I have also attached the full code. Help me with debugging this problem.
import React, { Component, Suspense } from 'react'
import { Layout, Menu } from 'antd';
import {TagFilled, SettingFilled , FileAddOutlined, DeleteFilled, LogoutOutlined } from '#ant-design/icons';
import { renderRoutes } from 'react-router-config';
import { loadLabels, deleteLabel} from '../../Store/Action/label'
import { logout } from '../../Store/Action/auth'
import { connect } from 'react-redux';
import Dialog from '#material-ui/core/Dialog';
import DialogActions from '#material-ui/core/DialogActions';
import DialogContent from '#material-ui/core/DialogContent';
import DialogTitle from '#material-ui/core/DialogTitle';
import Button from '#material-ui/core/Button';
import AddLabel from './Components/AddLabel'
import SideBar from './Components/SideBar'
import Avatar from '#material-ui/core/Avatar';
import {Dropdown} from 'react-bootstrap'
import Card from '#material-ui/core/Card';
import CardContent from '#material-ui/core/CardContent';
import { Row, Col, ListGroup } from 'react-bootstrap';
import Typography from '#material-ui/core/Typography';
import Divider from '#material-ui/core/Divider';
import ListSubheader from '#material-ui/core/ListSubheader';
import List from '#material-ui/core/List';
import ListItem from '#material-ui/core/ListItem';
import ListItemIcon from '#material-ui/core/ListItemIcon';
import ListItemText from '#material-ui/core/ListItemText';
import { Redirect } from 'react-router-dom';
const { Header, Content, Footer, Sider } = Layout;
export class HomePage extends Component {
//Constructor
constructor(){
super()
this.state = {
collapsed: false,
addLabelVisible: false,
isHovered: {},
anchorEl: null,
setAnchorEl: null
};
this.addLabelToggle = this.addLabelToggle.bind(this)
this.handleMouseEnter = this.handleMouseEnter.bind(this);
this.handleMouseLeave = this.handleMouseLeave.bind(this);
this.handlelogOut = this.handlelogOut.bind(this);
this.fetchData = this.fetchData.bind(this);
}
//Collapse the Sidebar
onCollapse = collapsed => {
this.setState({ collapsed });
};
//Toogle Add Label Dialog
addLabelToggle(addLabelVisible) {
this.setState({ addLabelVisible });
}
//Fetch All labels from the API
componentDidMount(){
console.log('problem here 1')
this.props.loadLabels()
}
//API CAll
fetchData(){
this.props.loadLabels()
}
//Called Whenever new Label is Added
componentDidUpdate(prevProps) {
if(typeof(prevProps.labels) === 'undefined' ) {
this.fetchData()
}
else if(prevProps.labels === this.props.labels){
this.fetchData()
}else{
}
}
//Hover
handleMouseEnter = index => {
this.setState(prevState => {
return { isHovered: { ...prevState.isHovered, [index]: true } };
});
};
//Hover
handleMouseLeave = index => {
this.setState(prevState => {
return { isHovered: { ...prevState.isHovered, [index]: false } };
});
};
//Delete a Label
handleLabelDelete(id){
const data = {
id: id,
img: 'https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png'
}
this.props.deleteLabel(data)
}
handleClick = (event) => {
this.setState({
anchorEl: event.currentTarget
})
};
handleClose = () => {
this.setState({
anchorEl: null
})
};
handlelogOut = (e) =>{
console.log('logout')
this.props.logout()
}
nextPath(path) {
this.props.history.push(path);
}
render() {
const open = Boolean(this.anchorEl);
const id = open ? 'simple-popover' : undefined;
const { arr, isHovered } = this.state;
console.log(this.props.request)
if(!this.props.isAuthenticated){
this.nextPath('/account/login')
}
return (
<Layout style={{ minHeight: '100vh' }}>
{/* Navbar */}
<Header className="header" style={{ height: '60px', backgroundColor: '#1a243a' }}>
<div style={{ width: '120px', height: '31px', float: 'left', margin: '16px 28px 16px 0' }}>
<h2 style={{ color: 'white' }}>Nexdo</h2>
</div>
<div style={{ float: 'right' }}>
<Dropdown>
<Dropdown.Toggle style={{ backgroundColor: 'transparent', borderColor: 'transparent' }} id="dropdown-basic">
<Avatar>{this.props.user?this.props.user.first_name.slice(0,1):""}</Avatar>
</Dropdown.Toggle>
<Dropdown.Menu>
<Card style={{ background: '#ffffff', boxShadow: 'none', width: '280px' }}>
<CardContent>
<Row>
<Col xs={9}>
<Typography style={{ alignContent: 'right', justifyContent: 'right', display: 'flex' }} variant="h6" noWrap>
{this.props.user?this.props.user.first_name:""} {this.props.user?this.props.user.last_name:""}
</Typography>
<Typography style={{ color: '#333333', fontSize: '11px' , alignContent: 'right', justifyContent: 'right', display: 'flex' }} variant="h6" noWrap>
{this.props.user?this.props.user.email:""}
</Typography>
</Col>
<Col xs={3}>
<Avatar>{this.props.user?this.props.user.first_name.slice(0,1):""}</Avatar>
</Col>
</Row>
</CardContent>
<Divider />
<List
component="nav"
aria-labelledby="nested-list-subheader"
subheader={
<ListSubheader component="div" id="nested-list-subheader">
Actions
</ListSubheader>
}
>
<ListItem button>
<ListItemIcon>
<SettingFilled />
</ListItemIcon>
<ListItemText primary="Profile" />
</ListItem>
<a onClick={this.handlelogOut}>
<ListItem button>
<ListItemIcon>
<LogoutOutlined />
</ListItemIcon>
<ListItemText primary="Logout" />
</ListItem>
</a>
</List>
</Card>
</Dropdown.Menu>
</Dropdown>
</div>
</Header>
{/* SideBar and Content */}
<Layout className="site-layout">
<SideBar labelData = {this.props.labels} addLabelToggle = {this.addLabelToggle}/>
{/* Content which will be loaded dynamically */}
<Content style={{ margin: '0 16px' }}>
<main style={{ backgroundColor: "#fafafa", minHeight: '-webkit-fill-available' }} >
<Suspense fallback={<div>Loading...</div>}>
{renderRoutes(this.props.route.routes,)}
</Suspense>
</main>
</Content>
</Layout>
{/* Footer */}
<Footer style={{ textAlign: 'center' }}>Joan Louji ©2020 Created by Joan Louji</Footer>
{/* Add Label Dialog Box */}
<Dialog scroll="paper" open={this.state.addLabelVisible} onClose={()=>this.addLabelToggle(false)} aria-labelledby="scroll-dialog-title" aria-describedby="scroll-dialog-description">
<DialogTitle id="form-dialog-title"><b>Labels</b></DialogTitle>
<DialogContent>
<div style={{ height: "400px", width: "300px" }}>
{/* Display the Add Label Box */}
<AddLabel editClassName="form-control" value="Create a new Label" />
{this.props.labels?(this.props.labels.length==0?
<div style={{ margin: "0 auto", fontSize: '60px' ,display: 'flex' ,justifyContent: 'center', alignContent: 'center', alignItems: 'center', height: '100%', color: '#e0ebff'}}>
<div className="row">
<div className="col-12">
<FileAddOutlined style={{ margin: "0 auto", fontSize: '60px' ,display: 'flex' ,justifyContent: 'center', alignContent: 'center', alignItems: 'center', height: '100%', width: '100%' ,color: '#e0ebff'}}/>{"\n"}
</div>
<div className="col-12">
<h3 style={{ margin: "0 auto", fontSize: '20px' ,display: 'flex' ,justifyContent: 'center', alignContent: 'center', alignItems: 'center', height: '100%', width: '100%' ,color: '#e0ebff', marginTop: '20px'}}>Label Not Found</h3>
</div>
</div>
</div>
:
""
):"sd"}
{/* Render All the Labels in the Dialog Box */}
{this.props.labels?this.props.labels.map((data,index)=>{
return(
<div style={{ marginTop: '20px', }} >
<div key={data.name}>
<div className="row">
<div className="col-1" onMouseEnter={()=>this.handleMouseEnter(index)} onMouseLeave={()=>this.handleMouseLeave(index)}>
{this.state.isHovered[index]?
<DeleteFilled style={{ fontSize: 17, color: 'grey', cursor: 'pointer' }} onClick={(e)=>this.handleLabelDelete(data._id)}/>
:
<TagFilled style={{ fontSize: 17, color: 'grey' }}/>
}
</div>
<div className="col-9">
{data.name}
</div>
</div>
</div>
</div>
)
}):
<div>
<FileAddOutlined />
</div>
}
</div>
</DialogContent>
<DialogActions>
<Button onClick={(e)=>{
this.addLabelToggle(false)
}}>Done</Button>
</DialogActions>
</Dialog>
</Layout>
);
}
}
//mapStateToProps
const mapStateToProps = (state) => ({
isLoading: state.labels.isLoading,
user: state.auth.user,
labels: state.labels.labels,
});
export default connect(mapStateToProps, {loadLabels, deleteLabel, logout})(HomePage)
From the error, it is clear that there "IF" condition you have mentioned in the ComponentDidUpdate is calling setState repeatedly. That's why the react framework limits.
Please refer Component Did Update
I recently started learning about the Material UI. To develop a basic website structure while checking the basic template code.
However, certain items in the menu bar are not on the right side as in the example. I have taken most of the code as is and merged it, and I wonder why it doesn't move to the right.
CodeSandBox URL
Here's my full code but it seems quite long so I also add codesandbox URL
Full Code
import React from "react";
import clsx from "clsx";
import { makeStyles, useTheme } from "#material-ui/core/styles";
import Drawer from "#material-ui/core/Drawer";
import CssBaseline from "#material-ui/core/CssBaseline";
import AppBar from "#material-ui/core/AppBar";
import Toolbar from "#material-ui/core/Toolbar";
import List from "#material-ui/core/List";
import Typography from "#material-ui/core/Typography";
import Divider from "#material-ui/core/Divider";
import IconButton from "#material-ui/core/IconButton";
import MenuIcon from "#material-ui/icons/Menu";
import ChevronLeftIcon from "#material-ui/icons/ChevronLeft";
import ChevronRightIcon from "#material-ui/icons/ChevronRight";
import ListItem from "#material-ui/core/ListItem";
import ListItemIcon from "#material-ui/core/ListItemIcon";
import ListItemText from "#material-ui/core/ListItemText";
import InboxIcon from "#material-ui/icons/MoveToInbox";
import MailIcon from "#material-ui/icons/Mail";
import Badge from "#material-ui/core/Badge";
import Menu from "#material-ui/core/Menu";
import MenuItem from "#material-ui/core/MenuItem";
import NotificationsIcon from "#material-ui/icons/Notifications";
import AccountCircle from "#material-ui/icons/AccountCircle";
import MoreIcon from "#material-ui/icons/MoreVert";
const drawerWidth = 240;
const useStyles = makeStyles(theme => ({
root: {
display: "flex"
},
appBar: {
transition: theme.transitions.create(["margin", "width"], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen
})
},
appBarShift: {
width: `calc(100% - ${drawerWidth}px)`,
marginLeft: drawerWidth,
transition: theme.transitions.create(["margin", "width"], {
easing: theme.transitions.easing.easeOut,
duration: theme.transitions.duration.enteringScreen
})
},
menuButton: {
marginRight: theme.spacing(2)
},
hide: {
display: "none"
},
drawer: {
width: drawerWidth,
flexShrink: 0
},
drawerPaper: {
width: drawerWidth
},
drawerHeader: {
display: "flex",
alignItems: "center",
padding: theme.spacing(0, 1),
...theme.mixins.toolbar,
justifyContent: "flex-end"
},
content: {
flexGrow: 1,
padding: theme.spacing(3),
transition: theme.transitions.create("margin", {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen
}),
marginLeft: -drawerWidth
},
contentShift: {
transition: theme.transitions.create("margin", {
easing: theme.transitions.easing.easeOut,
duration: theme.transitions.duration.enteringScreen
}),
marginLeft: 0
}
}));
export default function User() {
const classes = useStyles();
const theme = useTheme();
const [open, setOpen] = React.useState(false);
const handleDrawerOpen = () => {
setOpen(true);
};
const handleDrawerClose = () => {
setOpen(false);
};
// TEST
const [anchorEl, setAnchorEl] = React.useState(null);
const [mobileMoreAnchorEl, setMobileMoreAnchorEl] = React.useState(null);
const isMenuOpen = Boolean(anchorEl);
const isMobileMenuOpen = Boolean(mobileMoreAnchorEl);
const handleProfileMenuOpen = event => {
setAnchorEl(event.currentTarget);
};
const handleMobileMenuClose = () => {
setMobileMoreAnchorEl(null);
};
const handleMenuClose = () => {
setAnchorEl(null);
handleMobileMenuClose();
};
const handleMobileMenuOpen = event => {
setMobileMoreAnchorEl(event.currentTarget);
};
const menuId = "primary-search-account-menu";
const renderMenu = (
<Menu
anchorEl={anchorEl}
anchorOrigin={{ vertical: "top", horizontal: "right" }}
id={menuId}
keepMounted
transformOrigin={{ vertical: "top", horizontal: "right" }}
open={isMenuOpen}
onClose={handleMenuClose}
>
<MenuItem onClick={handleMenuClose}>Profile</MenuItem>
<MenuItem onClick={handleMenuClose}>My account</MenuItem>
</Menu>
);
const mobileMenuId = "primary-search-account-menu-mobile";
const renderMobileMenu = (
<Menu
anchorEl={mobileMoreAnchorEl}
anchorOrigin={{ vertical: "top", horizontal: "right" }}
id={mobileMenuId}
keepMounted
transformOrigin={{ vertical: "top", horizontal: "right" }}
open={isMobileMenuOpen}
onClose={handleMobileMenuClose}
>
<MenuItem>
<IconButton aria-label="show 4 new mails" color="inherit">
<Badge badgeContent={4} color="secondary">
<MailIcon />
</Badge>
</IconButton>
<p>Messages</p>
</MenuItem>
<MenuItem>
<IconButton aria-label="show 11 new notifications" color="inherit">
<Badge badgeContent={11} color="secondary">
<NotificationsIcon />
</Badge>
</IconButton>
<p>Notifications</p>
</MenuItem>
<MenuItem onClick={handleProfileMenuOpen}>
<IconButton
aria-label="account of current user"
aria-controls="primary-search-account-menu"
aria-haspopup="true"
color="inherit"
>
<AccountCircle />
</IconButton>
<p>Profile</p>
</MenuItem>
</Menu>
);
return (
<div className={classes.root}>
<CssBaseline />
<AppBar
position="fixed"
className={clsx(classes.appBar, {
[classes.appBarShift]: open
})}
>
<Toolbar>
<IconButton
color="inherit"
aria-label="open drawer"
onClick={handleDrawerOpen}
edge="start"
className={clsx(classes.menuButton, open && classes.hide)}
>
<MenuIcon />
</IconButton>
<Typography variant="h6" noWrap>
LiveToday
</Typography>
<div className={classes.grow} />
<div className={classes.sectionDesktop}>
<IconButton aria-label="show 4 new mails" color="inherit">
<Badge badgeContent={4} color="secondary">
<MailIcon />
</Badge>
</IconButton>
<IconButton aria-label="show 17 new notifications" color="inherit">
<Badge badgeContent={17} color="secondary">
<NotificationsIcon />
</Badge>
</IconButton>
<IconButton
edge="end"
aria-label="account of current user"
aria-controls={menuId}
aria-haspopup="true"
onClick={handleProfileMenuOpen}
color="inherit"
>
<AccountCircle />
</IconButton>
</div>
<div className={classes.sectionMobile}>
<IconButton
aria-label="show more"
aria-controls={mobileMenuId}
aria-haspopup="true"
onClick={handleMobileMenuOpen}
color="inherit"
>
<MoreIcon />
</IconButton>
</div>
</Toolbar>
</AppBar>
<Drawer
className={classes.drawer}
variant="persistent"
anchor="left"
open={open}
classes={{
paper: classes.drawerPaper
}}
>
<div className={classes.drawerHeader}>
<IconButton onClick={handleDrawerClose}>
{theme.direction === "ltr" ? (
<ChevronLeftIcon />
) : (
<ChevronRightIcon />
)}
</IconButton>
</div>
<Divider />
<List>
{["Inbox", "Starred", "Send email", "Drafts"].map((text, index) => (
<ListItem button key={text}>
<ListItemIcon>
{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}
</ListItemIcon>
<ListItemText primary={text} />
</ListItem>
))}
</List>
<Divider />
<List>
{["All mail", "Trash", "Spam"].map((text, index) => (
<ListItem button key={text}>
<ListItemIcon>
{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}
</ListItemIcon>
<ListItemText primary={text} />
</ListItem>
))}
</List>
</Drawer>
<main
className={clsx(classes.content, {
[classes.contentShift]: open
})}
>
<div className={classes.drawerHeader} />
</main>
{renderMobileMenu}
{renderMenu}
</div>
);
}
The div which is responsible for pushing icons to the right is using className={classes.grow}, but you haven't defined grow anywhere.
Add the following code to your makeStyles function:
grow: {
flexGrow: 1
}
It will be better if I demonstrate with images.
This is what I am trying to achieve. Assume landscape mode tablet size. Let's say I have X amount of elements in array. I want to map it across the row until it has 3 items in a row, then goes down. With bootstrap, I can do something like col-md-4 three times.
Currently I am using native-base. It has an interesting grid systems, but not exactly what I wanted.
This is what I have right now:
<Grid>
<Row>
{ recipeStore.categories.map((category, index) => {
return (
<Col key={index} style={{height: 300}}>
<Card>
<CardItem>
<Body>
<Text>{ category.name }</Text>
</Body>
</CardItem>
</Card>
</Col>
)
})}
</Row>
</Grid>
How can I get the array iteration to fill out 3 columns then goes to the next row?
You can use flexWrap: 'wrap' on the parent contain and then use flexBasis on the children.
import React, { Component } from 'react';
import { View, StyleSheet } from 'react-native';
const ABox = () => <View style={styles.box} />;
export default class App extends Component {
render() {
return (
<View style={styles.container}>
<ABox />
<ABox />
<ABox />
<ABox />
<ABox />
<ABox />
<ABox />
<ABox />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexWrap: 'wrap',
flexDirection: 'row',
paddingTop: 20,
},
box: {
flexBasis: 75,
borderWidth: 1,
borderColor: 'black',
height: 40,
margin: 10,
}
});
Snack: https://snack.expo.io/HkUFUp7ub
The best way to do this is using the FlatList it is good in performance and easy to use. And it is recommended for making a list (see this). Additionally you don't need to add any extra package to your project.
You can easily use the FlatList as below:
_keyExtractor = (item, index) => index;
_renderItem = ({item: category}) => (
<Card>
<CardItem>
<Body>
<Text>{ category.name }</Text>
</Body>
</CardItem>
</Card>
);
render() {
return (
<FlatList
numColumns={3}
data={recipeStore.categories}
keyExtractor={this._keyExtractor}
renderItem={this._renderItem}
/>
);
}
Note: you should use the numColumns peroperty to define the number of items in each row.
You can see the documentation of FlatList in here.
I'm trying to slide up some part of my app.
I searched for some info and I found out this post here in Stackoverflow -> How to auto-slide the window out from behind keyboard when TextInput has focus?
The thing is that my app is a little bit different and I don't know where to put the Scrollview tags.
I got this distribution:
<View style={ styles.container }>
<View style={ styles.header }>
<View style={ styles.headerTextContainer }>
<Text style={ styles.headerText } onPress={() => this.refs.listView.getScrollResponder().scrollTo(0) }>Parte { this.props.partNumber } - { this.state.totalComments } comentarios</Text>
</View>
</View>
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderComment}
style={ styles.content }
ref="listView" />
<View style={ styles.footer }>
<View style={ styles.footerTextInputContainer }>
<TextInput
style={ styles.footerTextInput }
onChangeText={(text) => console.log(text) }
placeholder="Escribe un comentario" />
</View>
<TouchableHighlight onPress={() => console.log("SEND COMMENT") } underlayColor="#ffffff">
<View style={ styles.footerSendButtonContainer }>
<Text style={ styles.footerSendButton }>Enviar</Text>
</View>
</TouchableHighlight>
</View>
</View>
The only thing I want to slide up when keyboard appears is the footer View.
I hope someone can help me out.
Thank you :)
I was be able to do it by using this component: react-native-keyboard-spacer
Thanks!
This is my solution:
const [keyboardHeight, setKeyboardHeight] = useState("10%");
useEffect(() => {
const keyboardDidShowListener = Keyboard.addListener(
'keyboardDidShow',
() => {
setKeyboardHeight("15%"); // or some other action
}
);
const keyboardDidHideListener = Keyboard.addListener(
'keyboardDidHide',
() => {
setKeyboardHeight("10%"); // or some other action
}
);
return () => {
keyboardDidHideListener.remove();
keyboardDidShowListener.remove();
};
}, []);
And in the view:
<View style={[globalStyles.footer, {height: keyboardHeight}]}>
//PUT YOUR VIEW FOOTER HERE
</View>