React Router - How to route to a specific path within a loop - reactjs

I am bit stuck and cannot find any similar issue.
In my application, I am looping over some data that I need to render but I am not sure how to use react-router in this case.
I would like to access to the project.pathname field in order to redirect to my Link.
But I am pretty sure its the wrong way.
All my routes are defined in my App.js file already but how to access this here ?
Here is my code snippet:
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { Link } from 'react-router-dom'
import { withStyles } from '#material-ui/core/styles'
import Grid from '#material-ui/core/Grid'
import Typography from '#material-ui/core/Typography'
import Button from '#material-ui/core/Button'
// import Staces from '../assets/staces.png'
import SteffProject from '../assets/steffProject.jpg'
import AxtradeProject from '../assets/axtradeProject.jpg'
import HotspawtsProject from '../assets/hotspawtsProject.jpg'
import IbizaProject from '../assets/ibizaProject.jpg'
import CdaProject from '../assets/cdaProject.png'
const projectImages = [
{
img: CdaProject,
projectName: 'CARRE DARTISTES',
headline: 'Artist’s shop Back office ',
type: 'Web application',
id: 1,
pathname: '/AboutMe'
},
{
img: IbizaProject,
projectName: 'IBIZA',
headline: 'Accounting Platform ',
type: 'Web application',
id: 2,
pathname: '/Ibiza',
},
{
img: SteffProject,
projectName: 'STEFF',
headline: 'Deliveries Management',
type: 'Mobile application',
id: 3,
payhname: '/Steff',
},
{
img: HotspawtsProject,
projectName: 'HOTSPAWTS',
headline: 'Dog Sitting Platform ',
type: 'Mobile application',
id: 4,
pathname: '/Hotspawts',
},
{
img: AxtradeProject,
projectName: 'AXTRADE',
headline: 'Brokers platform ',
type: 'Web application',
id: 5,
pathname: '/Axtrade',
},
]
#withStyles((theme) => ({ // eslint-disable-line
projectPage: {
marginTop: 5,
backgroundColor: '#eee',
},
container: {
position: 'relative',
},
projectImage: {
width: '100%',
height: 'auto',
filter: 'grayscale(100%)',
},
title: {
color: '#fff',
position: 'absolute',
top: 20,
left: 10,
},
subheading: {
color: '#fff',
position: 'absolute',
top: 40,
left: 10,
},
caption: {
color: '#fff',
position: 'absolute',
top: 60,
left: 10,
},
display1: {
textAlign: 'center',
marginBottom: 20,
marginTop: 20,
},
raised: {
backgroundColor: '#424246',
marginTop: 10,
color: '#fff',
},
projectButton: {
position: 'absolute',
bottom: 10,
right: 10,
color: '#fff',
},
}))
export default class Projects extends Component {
static propTypes = {
classes: PropTypes.any.isRequired, // eslint-disable-line
}
render() {
const { classes } = this.props
return (
<Grid container className={classes.projectPage} alignItems="center" direction="column">
<Grid item>
<Typography className={classes.display1} variant="display1">Latest Projects</Typography>
</Grid>
<Grid item>
{projectImages.map(project => (
<div className={classes.container}>
<img
className={classes.projectImage}
key={project.id}
src={project.img}
alt={project.title}
/>
<Typography
className={classes.title}
variant="title"
>
{project.projectName}
</Typography>
<Typography className={classes.subheading} variant="subheading">{project.headline}</Typography>
<Typography className={classes.caption} variant="caption">{project.type}</Typography>
<Button className={classes.projectButton} component={Link} to={project.pathname}>project details</Button>
</div>
))}
</Grid>
<Grid item>
<Button className={classes.raised} size="medium" variant="raised">View more projects</Button>
</Grid>
</Grid>
)
}
}

You have typo in
{
img: SteffProject,
projectName: 'STEFF',
headline: 'Deliveries Management',
type: 'Mobile application',
id: 3,
payhname: '/Steff',
}
It should be pathname. I believe your code should work after fixing it.

Related

MuiTabPanl-Root Padding remove using CSS or Mui Styles?

I want to override the MUI Tab Panel Padding. I override the .MuiTabPanel-Root Class globally and inline style. But, the Tab Panel is not override. Screenshot and Code Below attached.
I want to remove the padding from the MuiTabPanel-Root class padding.
When I applied the padding as 0px in "MuiTabPanel-Root" class is not working.
But, When I remove the padding from this class .css-13xfq8m-MuiTabPanel-root Tab panel padding was removed. I don't know how to override the "TabPanel-root padding" using react js
CSS Global :
.MuiTabPanel-root{
padding: 0px;
}
CSS Inline :
<TabPanel value="1" classes={{
"& .MuiTabPanel-root": {
padding: "0px",
},
}}>
Full Code Tab Component :
import * as React from 'react';
import Box from '#mui/material/Box';
import Tab from '#mui/material/Tab';
import TabContext from '#mui/lab/TabContext';
import TabList from '#mui/lab/TabList';
import TabPanel from '#mui/lab/TabPanel';
import HistoryTable from '../HistoryTable/HistoryTable';
import { Button } from '#mui/material';
import SampleTable from './SampleTable';
import './TradeTab.css';
import { MuiThemeProvider, createTheme } from "#material-ui/core/styles";
import { orange, pink, green } from "#material-ui/core/colors";
export default function SampleTabControl() {
const theme = createTheme({
overrides: {
MuiTabs: {
indicator: {
backgroundColor: 'red'
}
},
MuiTab: {
root: {
"&:hover": {
backgroundColor: pink[100],
color: pink[700]
},
".MuiTabPanel-root":{
padding:0
}
},
selected: {
backgroundColor: orange[100],
color: orange[700],
"&:hover": {
backgroundColor: 'green',
color: green[700]
}
}
}
}
});
const [value, setValue] = React.useState('1');
const handleChange = (event, newValue) => {
setValue(newValue);
};
return (
<MuiThemeProvider theme={theme}>
<Box sx={{ width: '100%', typography: 'body1'}}>
<TabContext value={value}>
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
<TabList onChange={handleChange} aria-label="lab API tabs example">
<Tab label="Item One" value="1" style={{color: "white", fontWeight:"500"}}
sx={{backgroundColor: value=="1" ? "blue" : "lightgrey" }}/>
<Tab label="Item Two" value="2" style={{color: "white", fontWeight:"500", marginLeft:'10px'}}
sx={{backgroundColor: value=="2" ? "blue" : "lightgrey"}}/>
<Button variant='outlined' style={{marginLeft:'100px', size:'small', height:'30px', marginTop:"10px"}}>1X</Button>
</TabList>
</Box>
<TabPanel value="1" classes={{
"& .MuiTabPanel-root": {
padding: "0px",
},
}}>
<SampleTable/>
</TabPanel>
<TabPanel value="2">Item Two</TabPanel>
<TabPanel value="3">Item Three</TabPanel>
</TabContext>
</Box>
</MuiThemeProvider>
);
}
Full Code Table :
import React, { useMemo } from 'react';
import MaterialReactTable from 'material-react-table';
import { makeStyles } from '#mui/styles';
//nested data is ok, see accessorKeys in ColumnDef below
const data = [
{
name: {
firstName: 'John',
lastName: 'Doe',
},
address: '261 Erdman Ford',
city: 'East Daphne',
state: 'Kentucky',
},
{
name: {
firstName: 'Jane',
lastName: 'Doe',
},
address: '769 Dominic Grove',
city: 'Columbus',
state: 'Ohio',
},
{
name: {
firstName: 'Joe',
lastName: 'Doe',
},
address: '566 Brakus Inlet',
city: 'South Linda',
state: 'West Virginia',
},
{
name: {
firstName: 'Kevin',
lastName: 'Vandy',
},
address: '722 Emie Stream',
city: 'Lincoln',
state: 'Nebraska',
},
{
name: {
firstName: 'Joshua',
lastName: 'Rolluffs',
},
address: '32188 Larkin Turnpike',
city: 'Charleston',
state: 'South Carolina',
},
];
const SampleTable = () => {
//should be memoized or stable
const columns = useMemo(
() => [
{
accessorKey: 'name.firstName', //access nested data with dot notation
header: 'First Name',
},
{
accessorKey: 'name.lastName',
header: 'Last Name',
},
{
accessorKey: 'address', //normal accessorKey
header: 'Address',
},
{
accessorKey: 'city',
header: 'City',
},
{
accessorKey: 'state',
header: 'State',
},
],
[],
);
return <MaterialReactTable columns={columns} data={data} style={{padding:'0px'}}/>;
};
export default SampleTable;
I try to remove the padding for "MuiTabPanel-root".
Expected Result :
Remove the padding from "MuiTabPanel-Root"

Material UI implementation in TypeScript

I am new to typeScript and I am using this materialUI premium theme OnePirate and I am using the Footer component and it is working perfectly fine in the js but when I am moving the same Footer component to my project and rename the component to .tsx It throws errors saying "No Overload matches this call"
Here is the code:
import React from "react";
import { makeStyles } from "#material-ui/core/styles";
import Grid from "#material-ui/core/Grid";
import Link from "#material-ui/core/Link";
import Container from "#material-ui/core/Container";
import Typography from "./materialUi/Typography";
import TextField from "./materialUi/TextField";
import fbicon from "./static/themes/onepirate/appFooterFacebook.png";
import twicon from "./static/themes/onepirate/appFooterTwitter.png";
const useStyles = makeStyles((theme) => ({
root: {
display: "flex",
backgroundColor: theme.palette.secondary.light,
},
container: {
marginTop: theme.spacing(8),
marginBottom: theme.spacing(8),
display: "flex",
},
iconsWrapper: {
height: 120,
},
icons: {
display: "flex",
},
icon: {
width: 48,
height: 48,
display: "flex",
justifyContent: "center",
alignItems: "center",
backgroundColor: theme.palette.warning.main,
marginRight: theme.spacing(1),
"&:hover": {
backgroundColor: theme.palette.warning.dark,
},
},
list: {
margin: 0,
listStyle: "none",
paddingLeft: 0,
},
listItem: {
paddingTop: theme.spacing(0.5),
paddingBottom: theme.spacing(0.5),
},
language: {
marginTop: theme.spacing(1),
width: 150,
},
}));
const LANGUAGES = [
{
code: "en-US",
name: "English",
},
{
code: "fr-FR",
name: "Français",
},
];
function Footer() {
const classes = useStyles();
return (
<Typography component="footer" className={classes.root}>
<Container className={classes.container}>
<Grid container spacing={5}>
<Grid item xs={6} sm={4} md={3}>
<Grid
container
direction="column"
justify="flex-end"
className={classes.iconsWrapper}
spacing={2}
>
<Grid item className={classes.icons}>
<a href="https://material-ui.com/" className={classes.icon}>
<img src={fbicon} alt="Facebook" />
</a>
<a
href="https://twitter.com/MaterialUI"
className={classes.icon}
>
<img src={twicon} alt="Twitter" />
</a>
</Grid>
<Grid item>© 2019 Onepirate</Grid>
</Grid>
</Grid>
<Grid item xs={6} sm={4} md={2}>
<Typography variant="h6" marked="left" gutterBottom>
Legal
</Typography>
<ul className={classes.list}>
<li className={classes.listItem}>
<Link href="/premium-themes/onepirate/terms/">Terms</Link>
</li>
<li className={classes.listItem}>
<Link href="/premium-themes/onepirate/privacy/">Privacy</Link>
</li>
</ul>
</Grid>
<Grid item xs={6} sm={8} md={4}>
<Typography variant="h6" marked="left" gutterBottom>
Language
</Typography>
<TextField
select
SelectProps={{
native: true,
}}
className={classes.language}
>
{LANGUAGES.map((language) => (
<option value={language.code} key={language.code}>
{language.name}
</option>
))}
</TextField>
</Grid>
<Grid item>
<Typography variant="caption">
{"Icons made by "}
<Link
href="https://www.freepik.com"
rel="nofollow"
title="Freepik"
>
Freepik
</Link>
{" from "}
<Link
href="https://www.flaticon.com"
rel="nofollow"
title="Flaticon"
>
www.flaticon.com
</Link>
{" is licensed by "}
<Link
href="https://creativecommons.org/licenses/by/3.0/"
title="Creative Commons BY 3.0"
target="_blank"
rel="noopener noreferrer"
>
CC 3.0 BY
</Link>
</Typography>
</Grid>
</Grid>
</Container>
</Typography>
);
}
export default Footer;
This is the Typography code if I don't import from material UI
import React from "react";
import PropTypes from "prop-types";
import { withStyles } from "#material-ui/core/styles";
import { capitalize } from "#material-ui/core/utils";
import MuiTypography from "#material-ui/core/Typography";
const styles = (theme) => ({
markedH2Center: {
height: 4,
width: 73,
display: "block",
margin: `${theme.spacing(1)}px auto 0`,
backgroundColor: theme.palette.secondary.main,
},
markedH3Center: {
height: 4,
width: 55,
display: "block",
margin: `${theme.spacing(1)}px auto 0`,
backgroundColor: theme.palette.secondary.main,
},
markedH4Center: {
height: 4,
width: 55,
display: "block",
margin: `${theme.spacing(1)}px auto 0`,
backgroundColor: theme.palette.secondary.main,
},
markedH6Left: {
height: 2,
width: 28,
display: "block",
marginTop: theme.spacing(0.5),
background: "currentColor",
},
});
const variantMapping = {
h1: "h1",
h2: "h1",
h3: "h1",
h4: "h1",
h5: "h3",
h6: "h2",
subtitle1: "h3",
};
function Typography(props) {
const { children, classes, marked = false, variant, ...other } = props;
return (
<MuiTypography variantMapping={variantMapping} variant={variant} {...other}>
{children}
{marked ? (
<span
className={
classes[`marked${capitalize(variant) + capitalize(marked)}`]
}
/>
) : null}
</MuiTypography>
);
}
Typography.propTypes = {
children: PropTypes.node,
classes: PropTypes.object.isRequired,
marked: PropTypes.oneOf([false, "center", "left"]),
variant: PropTypes.string,
};
export default withStyles(styles)(Typography);
This is the error now:
TL;DR: I've open sourced my implementation of onepirate in Typescript so you can just use that: https://github.com/rothbart/onepirate-typescript
This is a great question. Onepirate is a great resource but as you've noticed it isn't really built in a way that's Typescript friendly.
Your problem here is that the Typography implementation in onepirate isn't doing a great job of specifying which properties it expects, and is relying on the fact that vanilla JS will mostly just pass everything through to the underlying MuiTypography component.
Here's a much cleaner Typography implementation that preserves the underline effect in onepirate works with Typescript:
import React from "react";
import PropTypes, { InferProps } from "prop-types";
import {
withStyles,
WithStyles,
createStyles,
Theme,
} from "#material-ui/core/styles";
import MuiTypography, { TypographyProps } from "#material-ui/core/Typography";
const styles = (theme: Theme) =>
createStyles({
markedH2Center: {
height: 4,
width: 73,
display: "block",
margin: `${theme.spacing(1)}px auto 0`,
backgroundColor: theme.palette.secondary.main,
},
markedH3Center: {
height: 4,
width: 55,
display: "block",
margin: `${theme.spacing(1)}px auto 0`,
backgroundColor: theme.palette.secondary.main,
},
markedH4Center: {
height: 4,
width: 55,
display: "block",
margin: `${theme.spacing(1)}px auto 0`,
backgroundColor: theme.palette.secondary.main,
},
markedH6Left: {
height: 2,
width: 28,
display: "block",
marginTop: theme.spacing(0.5),
background: "currentColor",
},
});
function getMarkedClassName(variant: string) {
switch (variant) {
case "h2":
return "markedH2Center";
case "h3":
return "markedH3Center";
case "h4":
return "markedH4Center";
}
return "markedH6Left";
}
const variantMapping = {
h1: "h1",
h2: "h1",
h3: "h1",
h4: "h1",
h5: "h3",
h6: "h2",
subtitle1: "h3",
};
function Typography<C extends React.ElementType>(
props: TypographyProps<C, { component?: C }> &
WithStyles<typeof styles> &
InferProps<typeof Typography.propTypes>
) {
const { children, variant, classes, marked, ...other } = props;
return (
<MuiTypography variantMapping={variantMapping} variant={variant} {...other}>
{children}
{marked ? (
<span className={classes[getMarkedClassName(variant as string)]} />
) : null}
</MuiTypography>
);
}
Typography.propTypes = {
marked: PropTypes.oneOf([false, "center", "left"]),
};
Typography.defaultProps = {
marked: false,
};
export default withStyles(styles)(Typography);
Just a heads up that will run into this same problem with other onepirate components as well (I just finished re-implementing most of them in Typescript so I could use them in my own web app). If you're trying to reverse engineer how I did this I'd pay particular attention to how I took advantage of MuiTypography props and then just added the one new property I needed (marked).
TypographyProps<C, { component?: C }> &
WithStyles<typeof styles> &
InferProps<typeof Typography.propTypes>
I'd also highly recommend reading over https://material-ui.com/guides/typescript/ if you haven't already, it's a super helpful guide for understanding some of the Typescript gotchas in Material-UI.

Initialize react hook in a class based component

I am trying to change the function-based component to the class-based component. I am getting an error while converting. How to initialize hook in a class component.
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:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
This is the error I am getting
Papebase Material UI
import React from 'react';
import PropTypes from 'prop-types';
import { createMuiTheme, ThemeProvider, withStyles } from '#material-ui/core/styles';
import CssBaseline from '#material-ui/core/CssBaseline';
import Hidden from '#material-ui/core/Hidden';
import Typography from '#material-ui/core/Typography';
import Link from '#material-ui/core/Link';
import Navigator from '../Components/Navigator';
import Content from './Content';
import Header from '../Components/Header';
import { Switch, Route, BrowserRouter, Link as RouteLink } from "react-router-dom";
import { connect } from 'react-redux';
import { logout } from '../actions/auth';
function Copyright() {
return (
<Typography variant="body2" color="textSecondary" align="center">
{'Copyright © '}
<Link color="inherit" href="https://material-ui.com/">
Podo
</Link>{' '}
{new Date().getFullYear()}
{'.'}
</Typography>
);
}
let theme = createMuiTheme({
palette: {
primary: {
light: '#63ccff',
main: '#009be5',
dark: '#006db3',
},
},
typography: {
h5: {
fontWeight: 500,
fontSize: 26,
letterSpacing: 0.5,
},
},
shape: {
borderRadius: 8,
},
props: {
MuiTab: {
disableRipple: true,
},
},
mixins: {
toolbar: {
minHeight: 48,
},
},
});
theme = {
...theme,
overrides: {
MuiDrawer: {
paper: {
backgroundColor: '#18202c',
},
},
MuiButton: {
label: {
textTransform: 'none',
},
contained: {
boxShadow: 'none',
'&:active': {
boxShadow: 'none',
},
},
},
MuiTabs: {
root: {
marginLeft: theme.spacing(1),
},
indicator: {
height: 3,
borderTopLeftRadius: 3,
borderTopRightRadius: 3,
backgroundColor: theme.palette.common.white,
},
},
MuiTab: {
root: {
textTransform: 'none',
margin: '0 16px',
minWidth: 0,
padding: 0,
[theme.breakpoints.up('md')]: {
padding: 0,
minWidth: 0,
},
},
},
MuiIconButton: {
root: {
padding: theme.spacing(1),
},
},
MuiTooltip: {
tooltip: {
borderRadius: 4,
},
},
MuiDivider: {
root: {
backgroundColor: '#404854',
},
},
MuiListItemText: {
primary: {
fontWeight: theme.typography.fontWeightMedium,
},
},
MuiListItemIcon: {
root: {
color: 'inherit',
marginRight: 0,
'& svg': {
fontSize: 20,
},
},
},
MuiAvatar: {
root: {
width: 32,
height: 32,
},
},
},
};
const drawerWidth = 256;
const styles = {
root: {
display: 'flex',
minHeight: '100vh',
},
drawer: {
[theme.breakpoints.up('sm')]: {
width: drawerWidth,
flexShrink: 0,
},
},
app: {
flex: 1,
display: 'flex',
flexDirection: 'column',
},
main: {
flex: 1,
padding: theme.spacing(6, 4),
background: '#eaeff1',
},
footer: {
padding: theme.spacing(2),
background: '#eaeff1',
},
};
export class Paperbase extends React.Component {
render() {
const { classes } = this.props;
const [mobileOpen, setMobileOpen] = React.useState(false);
const handleDrawerToggle = () => {
setMobileOpen(!mobileOpen);
};
return (
<BrowserRouter>
<ThemeProvider theme={theme}>
<div className={classes.root}>
<CssBaseline />
<nav className={classes.drawer}>
<Hidden smUp implementation="js">
<Navigator
PaperProps={{ style: { width: drawerWidth } }}
variant="temporary"
open={mobileOpen}
onClose={handleDrawerToggle}
/>
</Hidden>
<Hidden xsDown implementation="css">
<Navigator PaperProps={{ style: { width: drawerWidth } }} />
</Hidden>
</nav>
<div className={classes.app}>
<Header onDrawerToggle={handleDrawerToggle} />
<main className={classes.main}>
<Switch>
<Route exact path="/dashboard/auth" render={() => <Content /> } />
<Route path="/Inbox" render={() => <div> Page inbox</div>} />
<Route path="/Starred" render={() => <div>PSage starred</div>} />
</Switch>
</main>
<footer className={classes.footer}>
<Copyright />
</footer>
</div>
</div>
</ThemeProvider>
</BrowserRouter>
)
}
}
Paperbase.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(Paperbase);
Short answer you can't use react hooks on class based components.
Slightly longer answer:
Hooks were introduced to allow use of state in function components. If you're using a class component, then the mechanisms to manipulate state are built into the default class component behavior.
So in your example, you'd want to do something like:
Replace your state hook:
const [mobileOpen, setMobileOpen] = React.useState(false);
const handleDrawerToggle = () => {
setMobileOpen(!mobileOpen);
};
with a stateful class component and setState():
class PaperBase extends React.Component {
constructor(props){
super(props);
this.state = {
mobileOpen: true,
}
this.handleDrawerToggle = this.handleDrawerToggle.bind(this);
}
handleDrawerToggle = () => {
let mobileOpen = this.state.mobileOpen;
mobileOpen != mobileOpen;
this.setState = {
mobileOpen: mobileOpen,
}
}
// ...
}
Rather than explain how it all works here, I'll suggest reading the official tutorial on state in components: https://reactjs.org/docs/state-and-lifecycle.html

react-native-picker-select not Working with Parent View {flexDirection:'row'}

I want to use <RNPickerSelect./> with a <TextInput/> in a single row. So, when I make the Parent flexDirection: row, I see only the arrow and no text. Even if I remove the <TextInput/>, I don't see any text in the Picker.
import React, { Component } from 'react';
import {
StyleSheet,
View,
} from 'react-native';
import RNPickerSelect from 'react-native-picker-select';
type Props = {}
const countryCode = [
{
label: '+91',
value: '+91',
},
{
label: '+1',
value: '+1',
},
{
label: '+2',
value: '+2',
},
];
export default class PickerTest extends Component<Props> {
constructor() {
super()
this.state = {
phoneNumber: "",
countryCode: ""
}
}
render() {
return (
<View style={{flexDirection:'row'}}>
<View paddingVertical={5}>
{/* and hiding the InputAccessoryView on iOS */}
<RNPickerSelect
placeholder={{}}
items={countryCode}
onValueChange={value => {
this.setState({
countryCode: value,
});
}}
InputAccessoryView={() => null}
style={pickerSelectStyles}
value={this.state.countryCode}
/>
</View>
</View>
);
}
}
const pickerSelectStyles = StyleSheet.create({
inputIOS: {
fontSize: 16,
paddingVertical: 12,
paddingHorizontal: 10,
borderWidth: 1,
borderColor: 'gray',
borderRadius: 4,
color: 'black',
paddingRight: 30, // to ensure the text is never behind the icon
},
inputAndroid: {
fontSize: 16,
paddingHorizontal: 10,
paddingVertical: 8,
borderWidth: 0.5,
borderColor: 'purple',
borderRadius: 8,
color: 'black',
paddingRight: 30, // to ensure the text is never behind the icon
},
});
On running the above app, I get something like this
As you can see the picker is not showing the text.
Below are the configuration I am using
react-native-picker-select version: 6.3.3
react-native version: 0.61.2
react version: 16.9.0
this is an upstream issue: https://snack.expo.io/HkygCqhsr
options:
useNativeAndroidPickerStyle prop
set width and height with inputAndroid style prop
Add the atribute "pickerProps" to the RNPickerSelect with the option overflow: 'hidden'
<RNPickerSelect style={styles.selectContainer}
...
pickerProps={{ style: { height: 214, overflow: 'hidden' } }}
...
/>

multilevel nested list in material-ui next

I'd like to create multilevel nested list to display the menu on the left side - - very similar as on oficial site: https://material-ui-next.com/.
data source is in JSON where for each item there's also information about parent item and some other data - - this is the example:
{
"task_number": 1201092,
"task": "Monthly Cash Flow from Deliveries",
"task_parent_number": 1201090,
"task_parent": "Wholesale Cash Flow"
},
{
"task_number": 1201095,
"task": "Monthly Cash Flow from Fix Amounts",
"task_parent_number": 1201090,
"task_parent": "Wholesale Cash Flow"
},
{
"task_number": 1201100,
"task": "Wholesale Positions",
"task_parent_number": 1200007,
"task_parent": "Wholesale Contract Portfolio"
},
{
"task_number": 1201200,
"task": "All Wholesale Positions",
"task_parent_number": 1201100,
"task_parent": "Wholesale Positions"
}
I'am able to create an object with various nested elements - children - if they exist with followin function:
function getNestedChildren(arr, parent) {
var out = [];
for (var i in arr) {
if (arr[i].task_parent_number == parent) {
//console.log(i, arr[i].task_parent_number, arr[i].task_number);
var children = getNestedChildren(arr, arr[i].task_number);
if (children.length) {
arr[i].children = children;
}
out.push(arr[i]);
}
}
return out;
}
I've been following instructions for creating a nested list and importing it here: https://material-ui-next.com/demos/lists/#nested-list
..but I am not able to create a menu with nested elements as desired . . if someone can point me in the right direction would be great..
OK, i got this to work combining these 2 parts:
React example recursive render: https://gist.github.com/nkvenom/bf7b1adfe982cb47dee3
Material List guide here - https://medium.com/#ali.atwa/getting-started-with-material-ui-for-react-59c82d9ffd93
There is mui component.
I add recursion to the last example.
import type { SvgIconProps } from '#mui/material/SvgIcon';
import * as React from 'react';
import { styled } from '#mui/material/styles';
import Box from '#mui/material/Box';
import TreeView, { TreeViewProps } from '#mui/lab/TreeView';
import TreeItem, { TreeItemProps, treeItemClasses } from '#mui/lab/TreeItem';
import Typography from '#mui/material/Typography';
// import DeleteIcon from '#mui/icons-material/Delete';
// import Label from '#mui/icons-material/Label';
// import SupervisorAccountIcon from '#mui/icons-material/SupervisorAccount';
// import InfoIcon from '#mui/icons-material/Info';
// import ForumIcon from '#mui/icons-material/Forum';
// import LocalOfferIcon from '#mui/icons-material/LocalOffer';
import ArrowDropDownIcon from '#mui/icons-material/ArrowDropDown';
import ArrowRightIcon from '#mui/icons-material/ArrowRight';
declare module 'react' {
interface CSSProperties {
'--tree-view-color'?: string;
'--tree-view-bg-color'?: string;
}
}
type StyledTreeItemProps = TreeItemProps & {
bgColor?: string;
color?: string;
labelIcon?: React.ElementType<SvgIconProps>;
labelInfo?: React.ReactNode;
labelText: string;
};
type RecursiveStyledTreeItemProps = StyledTreeItemProps & {
childrenProps?: RecursiveStyledTreeItemProps[]
}
const StyledTreeItemRoot = styled(TreeItem)(({ theme }) => ({
color: theme.palette.text.secondary,
[`& .${treeItemClasses.content}`]: {
color: theme.palette.text.secondary,
borderTopRightRadius: theme.spacing(2),
borderBottomRightRadius: theme.spacing(2),
paddingRight: theme.spacing(1),
fontWeight: theme.typography.fontWeightMedium,
'&.Mui-expanded': {
fontWeight: theme.typography.fontWeightRegular,
},
'&:hover': {
backgroundColor: theme.palette.action.hover,
},
'&.Mui-focused, &.Mui-selected, &.Mui-selected.Mui-focused': {
backgroundColor: `var(--tree-view-bg-color, ${theme.palette.action.selected})`,
color: 'var(--tree-view-color)',
},
[`& .${treeItemClasses.label}`]: {
fontWeight: 'inherit',
color: 'inherit',
},
},
[`& .${treeItemClasses.group}`]: {
marginLeft: 0,
[`& .${treeItemClasses.content}`]: {
paddingLeft: theme.spacing(2),
},
},
}));
const RecursiveStyledTreeItem = ({ childrenProps, ...p }: RecursiveStyledTreeItemProps) => childrenProps
? <RecursiveStyledTreeItem {...p}>
{
childrenProps.map(cP => <RecursiveStyledTreeItem
key={cP.nodeId}
{...cP}
/>)
}
</RecursiveStyledTreeItem>
: < StyledTreeItem {...p} />
function StyledTreeItem(props: StyledTreeItemProps) {
const {
bgColor,
color,
labelIcon: LabelIcon = null,
labelInfo = null,
labelText,
...other
} = props;
return (
<StyledTreeItemRoot
label={
<Box sx={{ display: 'flex', alignItems: 'center', p: 0.5, pr: 0 }}>
{
LabelIcon && <Box component={LabelIcon} color="inherit" sx={{ mr: 1 }} />
}
<Typography variant="body2" sx={{ fontWeight: 'inherit', flexGrow: 1 }}>
{labelText}
</Typography>
{
labelInfo && <Typography variant="caption" color="inherit">
{labelInfo}
</Typography>
}
</Box>
}
style={{
'--tree-view-color': color,
'--tree-view-bg-color': bgColor,
}}
{...other}
/>
);
}
export default function CustomTreeView({ treeViewProps, items }: {
treeViewProps: Partial<TreeViewProps>
items: RecursiveStyledTreeItemProps[]
}) {
return (
<TreeView
// defaultExpanded={['3']}
defaultCollapseIcon={<ArrowDropDownIcon />}
defaultExpandIcon={<ArrowRightIcon />}
defaultEndIcon={<div style={{ width: 24 }} />}
sx={{ height: 264, flexGrow: 1, maxWidth: 400, overflowY: 'auto' }}
{...treeViewProps}
>
{items.map(item => <RecursiveStyledTreeItem
key={item.nodeId}
{...item}
/>)}
</TreeView>
);
}
There is mui-tree-select

Resources