ReactJS - getAttribute return null - reactjs

I have a problem with getAttribute() in my React code.
const handleChange = (event) => {
let selectM = event.target.getAttribute("data-minister_name");
console.log(selectM);
};
<List dense sx={{ width: '100%', maxWidth: 360, bgcolor: 'background.paper' }}>
{listMiniters.map((c) => (
<ListItem
key={c.label}
disablePadding
onClick={handleChange}
data-minister_name="{c.label}"
>
<ListItemButton>
<ListItemAvatar>
<Avatar
alt={`Avatar n°${c.label + 1}`}
src={`https://flagcdn.com/w20/${c.code.toLowerCase()}.png`}
/>
</ListItemAvatar>
<ListItemText id={c.label} primary={`Line item ${c.label + 1}`} />
</ListItemButton>
</ListItem>
))}
</List>
It return to my
null
I don't understand where come from the problem...? Could you help my please ?
I'm using MUI.

The event.target will be the element that was actually clicked which isn't, necessarily, the same as the element to which the event handler was bound.
The ListItem has a number of descendant elements which will intercept the click and be the event.target.
Use event.currentTarget instead.

Please try without '_' in your attribute name.
Altrernatively try with e.target.attributes.getNamedItem("aatribute-name").value;

Related

How to remove the paddingRight when a MUI Drawer is opened

My problem its quite simple but i not know how to solve that, when the Drawer from MaterialUI is opened are added some css into the body in my page, and one of the css add a padding-right and that are screwing the page indentation.
Drawer closed:
Drawer opened:
The problem:
Code:
<React.Fragment key={"menu-button"} >
<MenuIcon onClick={toggleDrawer(true)} />
<Drawer
anchor={"left"}
open={state}
onClose={toggleDrawer(false)}
>
<Box
sx={{ width: 250, height: '100%'}}
className={styles.background}
role="presentation"
onClick={toggleDrawer(false)}
onKeyDown={toggleDrawer(false)}
>
<List>
{['About me', 'Projects', 'Experience', 'Education'].map((text, index) => (
<ListItem key={text} disablePadding>
<ListItemButton className={styles.option}>
<ListItemIcon className={styles.optionIcon}>
{icons[index]}
</ListItemIcon>
<ListItemText primary={text} />
</ListItemButton>
</ListItem>
))}
</List>
</Box>
</Drawer>
</React.Fragment>
The styles are adding only colors.
I fixed adding "disableScrollLock={ true }" into the Drawer component :)

How do I link to another page in my MUI mini drawer sidebar?

I've tried to encapsulate my ListItem component with <Link to"/create> but it doesn't work, i've also tried using the history option but that confused me.
My codesandbox:
codesandbox.io/s/funny-einstein-deuqhi?file=/src/App.js
This is my sidebar.js (without all the imports and the creation of mixin&drawerheader and co, the link on the appbar to my createsite works, i want the same for my sidebar listitems. i want my listitem with the text ."add to-do" to link to the "\create" page):
const openedMixin = (theme) => (...);
const closedMixin = (theme) => (...);
const DrawerHeader = styled(...);
const AppBar = styled(...);
const Drawer = styled(...);
export default function MiniDrawer() {
const theme = useTheme();
const [open, setOpen] = React.useState(false);
const handleDrawerOpen = () => {
setOpen(true);
};
const handleDrawerClose = () => {
setOpen(false);
};
const itemsList = [
{
text: "Calendar",
icon: <EventAvailableOutlinedIcon style={{ fill: 'white' }} />,
},
{
text: "Add To-do",
icon: <AddBoxTwoToneIcon style={{ fill: 'white' }} />
}
]
return (
<Router>
<Box sx={{ display: 'flex' }}>
<CssBaseline />
<AppBar position="fixed" open={open} style={{ background: 'white' }}>
<Toolbar>
<IconButton
color="inherit"
aria-label="open drawer"
onClick={handleDrawerOpen}
edge="start"
sx={{
marginRight: 5,
...(open && { display: 'none' }),
}}
>
<MenuIcon style={{ fill: '#85CEE9' }} />
</IconButton>
<Link to="/create">create</Link>
<Typography variant="h6" noWrap component="div" style={{ color: "#85CEE9" }}>
project
</Typography>
</Toolbar>
</AppBar>
<Drawer variant="permanent" open={open}>
<DrawerHeader>
<IconButton onClick={handleDrawerClose}>
{theme.direction === 'rtl' ? <ChevronRightIcon style={{ fill: 'white' }} /> : <ChevronLeftIcon style={{ fill: 'white' }} />}
</IconButton>
</DrawerHeader>
<Divider />
<List>
{itemsList.map((item, index) => {
const { text, icon } = item;
return (
// <Link to="/create">
<Link to="/create">
<ListItem button component={Link} to="/create" onClick={onItemClick('Page 2')} key={text}>
{icon && <ListItemIcon >{icon}</ListItemIcon>}
// <ListItemText primary={text} style={{ color: "white" }} />
<Link to="/create">create</Link>
</ListItem>
</Link>
// </Link>
);
})}
</List>
</Drawer>
</Box>
</Router>
);
}```
In the sandbox you linked you weren't using the Link component at all in the drawer, so nothing was being linked to.
Render the ListItem component as a Link component and pass the appropriate link props.
Example:
const itemsList = [
{
text: "Calendar",
icon: <EventAvailableOutlinedIcon style={{ fill: "white" }} />,
to: "/create" // <-- add link targets
},
{
text: "Add To-do",
icon: <AddBoxTwoToneIcon style={{ fill: "white" }} />,
to: "/add-todo"
}
];
To the ListItem component, specify the Link component to be the component to render the list item as, and pass the current mapped item's to property.
<List>
{itemsList.map((item, index) => {
const { text, icon } = item;
return (
<ListItem component={Link} to={item.to} button key={text}>
{icon && <ListItemIcon>{icon}</ListItemIcon>}
<ListItemText primary={text} style={{ color: "white" }} />
</ListItem>
);
})}
</List>
Instead of using Link within your List component, use ListItem, ListItemButton, and ListItemText:
<List>
{['Inbox', 'Starred', 'Send email', 'Drafts'].map((text, index) => (
<ListItem key = {text} disablePadding>
<ListItemButton onClick = {handleNav} >
<ListItemIcon>
{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}
</ListItemIcon>
<ListItemText primary={text} />
</ListItemButton>
</ListItem>
))}
</List>
Create the method to pass to each ListItemButton's onClick:
import { useHistory } from 'react-router-dom'
const history = useHistory()
const handleNav = (event) =>
{
// Do whatever you need to do then push to the new page
history.push('/create')
}
Depending on what version of react-router you're using, your actual method to push to a new page may vary (useHistory for v5, useNavigate for v6, etc.).

how to focus an item programmatically reactjs

When page loaded, able to focus all items via pressing TAB,But there is pop up, I want to focus its child element on next press TAB instead of regular order when toggle.
popper element:
<Popper
aria-label="Profile Options"
open={open}
anchorEl={anchorRef.current}
role={undefined}
transition
>
{({ TransitionProps, placement }) => (
<Grow>
<Paper aria-label="Profile Options" style={DROPDOWN} variant="outlined">
<ClickAwayListener onClickAway={handleClose}>
<MenuList style={{ padding: 0 }} id="split-button-menu">
<div
ref={divRef} // target item!!
onKeyDown={e => {
if (e.key === 'Enter') {
handleMenuItemClick(3)
}
}}
role="link"
tabIndex={0}
>
<MenuItem onClick={event => handleMenuItemClick(3)} style={MENU_ITEM_3}>
<Text
style={{
fontFamily: uiStore.branding.font_family,
}}
text="Log Out"
variant="body1Medium"
/>
</MenuItem>
</div>
</MenuList>
</ClickAwayListener>
</Paper>
</Grow>
)}
</Popper>
toggle callback:
const divRef = React.useRef<HTMLDivElement>(null)
const handleToggle = () => {
anchorRef1?.current?.focus()// expect it to focus on item
setOpen(prevOpen => !prevOpen)
}
I need to see the focus effect as seem pic below when item focused programmatically.

React.js - Updating icon styles on component mount/unmount

I have an app that I'm building where it has a navigation bar down the left hand side with icons that open a modal when clicked on:
I have successfully set this up so that a different modal is loaded whenever the user clicks on one of the icons in the navigation bar and I'm now try to update state to highlight which icon's modal is loaded like the below:
To achieve this I am getting to grips with parent/child relationships and manipulating state.
The parent element renders a <div> that captures state:
<div>
<ActiveDashboardIcon data={this.state.data} />
</div>
I then have a child function that populates the parent <div>:
const ActiveDashboardIcon = ({ data }) =>
<div>
{data ? data :
<ListItem button id="dashboardIcon" style={{ backgroundColor: 'black' }}>
<ListItemIcon>
<DashboardIcon style={{ color: 'white' }} />
</ListItemIcon>
</ListItem>
}
</div>;
Lastly I am updating on componentDidMount and componentWillUnmount so that it updates the button styles (icon color and background color):
componentDidMount() {
this.setState({
data:
<ListItem button id="dashboardIcon" style={{ backgroundColor: 'white' }}>
<ListItemIcon>
<DashboardIcon style={{ color: 'black' }} />
</ListItemIcon>
</ListItem>
})
}
componentWillUnmount() {
this.setState({
data:
<ListItem button id="dashboardIcon" style={{ backgroundColor: 'black' }}>
<ListItemIcon>
<DashboardIcon style={{ color: 'white' }} />
</ListItemIcon>
</ListItem>
})
}
This works mostly as intended but I am struggling to accomplish a few things:
This current approach works for one icon/modal combination but is difficult to scale as I am unable to define different componentDidMount functions for each icon/modal combination
My current approach doesn't currently 'unselect' the icon and revert it to it's original style on componentWillUnmount
I can't work out how to include an onClick property for the icon:
onClick={this.openModal("dashboard")}. When I try to include it in the child element the browser cannot read property 'openModal' as it is part of the parent.
I am unsure of the best approach to achieve what I'm after.

React Component requires a unique key prop

I made an create component that renders everything that looks good, but when I do console in browser, it has below error.
index.js:2178 Warning: Each child in an array or iterator should have
a unique "key" prop.
I tried to have the key props but still has this error. Please see my code below and advise! Thank you very much.
const serviceList = (props) => (
<CardBody style={{ backgroundImage: `url(${ServiceBgImg})` }}>
<div>
<h3 style={{ fontWeight: 'bold' }}
>{props.groupName}</h3>
{props.allServices.filter(groupedServices => groupedServices.category === props.groupName)
.map(serviceInfo =>
<List component='nav'>
<ListItem>
<ListItemText primary={
<div key={serviceInfo.id}>
<h5 style={{ fontWeight: 'bold' }}>
<span>{serviceInfo.service}</span>
<span
style={{ float: 'right' }}
>{serviceInfo.price}</span>
</h5>
<h5>
{serviceInfo.description}
</h5>
</div>
}
/>
</ListItem>
</List>
)
}
</div>
</CardBody>
);
export default serviceList;
Your List component should wrap the map function, and inside that you add the key to mapped ListItems:
<List component='nav'>
...
.map((serviceInfo, index) =>
<ListItem key={index}>
...
</ListItem>
....
The outermost/parent element returned by the map function needs to have a key prop. In your case, it is not the <div> but <List>, which seems to be a mistake as it seems you wanted to loop over a filtered result of allServices to create a list of serviceInfo. If that's the case, you should move the map function just above the <ListItem> and assign key prop to it.
Code example as follow:
const serviceList = (props) => (
<div>
<h3 style={{ fontWeight: 'bold' }}>{props.groupName}</h3>
<List component='nav'>
{props.allServices.filter(groupedServices => groupedServices.category === props.groupName).map(serviceInfo =>
<ListItem key={serviceInfo.id}>
<ListItemText primary={
<div key={serviceInfo.id}>
<h5 style={{ fontWeight: 'bold' }}>
<span>{serviceInfo.service}</span>
<span
style={{ float: 'right' }}
>{serviceInfo.price}</span>
</h5>
<h5>{serviceInfo.description}</h5>
</div>
}/>
</ListItem>)}
</List>
</div>);
export default serviceList;

Resources