Error with "Collapsed inline menu" by Ant Design - reactjs

I am new to the world of react and javascript.
I encounter quite a mistake with the Ant Design code for the collapsed inline menu.
I tried several solutions found on the forum but without success.
And I do not quite understand the notion of one of the errors that is "Must Use destructuring state assignment"
I stick you my code and the errors that are indicated to me.
for the error "Missing Parentheses around multilines JSX" I have already tried the mettres but I have another error that appears.
when I click on the button nothing happens
I hope you can help me.
thank you in advance
import React, { Component } from 'react';
import { Menu, Icon, Button } from 'antd';
const { SubMenu } = Menu;
class RightVerticalMenu extends Component {
state = {
collapsed: false,
};
toggleCollapsed = () => {
this.setState({
collapsed: !this.state.collapsed,
});
};
render() {
const { collapsed } = this.state;
return (
<div className="right-menu" style={{ width: 256 }}>
<Button
type="primary"
onClick={this.toggleCollapsed}
style={{ marginBottom: 16 }}
>
<Icon type={this.toggleCollapsed ? 'menu-unfold' : 'menu-fold'} />
</Button>
<Menu
defaultSelectedKeys={['1']}
defaultOpenKeys={['sub1']}
mode="inline"
theme="dark"
inlineCollapsed={collapsed}
>
<SubMenu
key="sub1"
title={
<span>
<Icon type="mail" />
<span>Métérologie</span>
</span>
}
>
<Menu.Item key="5">Option 5</Menu.Item>
</SubMenu>
<SubMenu
key="sub2"
title={
<span>
<Icon type="appstore" />
<span>Chat</span>
</span>
}
>
<Menu.Item key="9">Option 9</Menu.Item>
<Menu.Item key="10">Option 10</Menu.Item>
</SubMenu>
</Menu>
</div>
);
}
}
export default RightVerticalMenu;
console errors :
Must Use destructuring state assignment[29, 19]
Missing Parentheses around multilines JSX[55, 15] and [67, 15]

Related

How to use custom isOpen with a chakra component

I am relatively new to react and not sure why isOpen is not working as expected.
Please see the code below for the example that I am working with
I have a menu icon that is using isOpen to open navlinks:
const { isOpen, onOpen, onClose } = useDisclosure();
<IconButton variant={"unstyled"} bgColor={"white"} color={"black"} size={"s"} icon={isOpen ? <Hamburger size={"24"} /> : <Hamburger size={"24"} />} aria-label={"Open Menu"} display={{ md: "none" }} onClick={isOpen ? onClose : onOpen} />
{isOpen ? (
<Box color={"#b8860b"} pb={4} display={{ md: "none" }}>
<Stack as={"nav"} spacing={5}>
{Links.map(link => (
<Link key={link.name} href={link.route}>
<Flex paddingBottom="40px" h="40px" borderBottom="1px" borderColor="black" justifyContent={'left'}>
<Flex paddingLeft={"10px"} paddingTop={"3%"}> {link.icon}</Flex>
<Text p={2} color={"black"} >
{link.name}
</Text>
</Flex>
</Link>
))}
</Stack>
</Box>
) : null}
When I try using a custom isOpen to open a drawer component, i just cant get it to work..
What am I doing wrong?:
const { isOpenMenu, onOpenMenu, onCloseMenu } = useDisclosure()
<Button
bgColor={"white"}
onClick={isOpenMenu}
>
<BsCart4 size={"26px"} color={"black"} />
{cartItemCount > 0 && <Badge ml='1' fontSize='0.9em' colorScheme='green'>{cartItemCount}</Badge>}
</Button>
<Drawer
isOpen={isOpenMenu}
placement='right'
onClose={onCloseMenu}
finalFocusRef={btnRef}
>
<DrawerOverlay />
<DrawerContent>
<DrawerCloseButton />
<DrawerHeader>Create your account</DrawerHeader>
<DrawerBody>
<Input placeholder='Type here...' />
</DrawerBody>
<DrawerFooter>
<Button variant='outline' mr={3} onClick={onCloseMenu}>
Cancel
</Button>
<Button colorScheme='blue'>Save</Button>
</DrawerFooter>
</DrawerContent>
</Drawer>
```
When I use isOpen for the drawer it works fine so I thought having another isOpen but custom would open the drawer but its not working as expected.
Can someone help understand why my thinking isnt right based on how to use isOpen correctly?
It seems like only isOpen works when I switch it from using the menu bar and drawer
First of all, if you want to use custom names to the useDisclosure states, you have to set them like this:
const { isOpen: isOpenMenu, onOpen: onOpenMenu, onClose: onCloseMenu } = useDisclosure()
Also, the onClose prop of the drawer component is just a event handler, dont put your onCloseMenu function ther, just call it when you want to close the drawer, as you made on the cancel button, example:
<Button onClick={onCloseMenu} ... />

on change of defaultOpenKeys values does not rer-ender antd menu component

What I want:
I want to open (expand) the submenu of a specific menu when I change/update the defaultOpenKeys value.
What I've tried:
const [submenu, setSubmenu] = useState([]);
useEffect(() => {
setSubmenu(["sub1"]);
}, []);
...
<Menu style={{ width: 256 }} defaultSelectedKeys={["4"]} defaultOpenKeys={submenu} mode="inline">
<Menu.Item key="1">Option 1</Menu.Item>
<Menu.Item key="2">Option 2</Menu.Item>
<SubMenu key="sub1" title="Submenu">
<Menu.Item key="3">Option 3</Menu.Item>
<Menu.Item key="4">Option 4</Menu.Item>
</SubMenu>
</Menu>;
In here, The submenu is an empty array at first, but whenever the page loads, useEffect does update the value of submenu and set to the ["sub1"]. What I believe is, whenever the state values do change, the page should re-render, so <Menu defaultOpenKeys={['sub1']} ...> should update like this, right?
But in here, if I pass <Menu defaultOpenKeys=['sub1'] ... > at first then this works as I expected, but If I pass the defaultOpenKeys value from the state, then this does not work as I expected (if the initial value of state is ['sub1'] then it also works fine).
Here is the code sandbox, where I've included both working and not working demo.
CODESANDBOX
Here is the screenshot:
UPDATED:
After #HDM91 answer,
I've tried with another prop provided by antd, which is openKeys and it does open the submenu at first, but was unable to close it, or even it does block other submenus from opening/closing.
<Menu
style={{ width: 256 }}
defaultSelectedKeys={["4"]}
openKeys={submenu} // blocks other submenu by closing and opening
mode="inline"
>
I've just tried with openKeys and and handle onOpenChange to set new openkeys into submenu state it's fine:
const [submenu, setSubmenu] = useState([]);
useEffect(() => {
setSubmenu(["sub1"]);
}, []);
return (
<Menu
style={{ width: 256 }}
defaultSelectedKeys={["4"]}
defaultOpenKeys={submenu}
openKeys={submenu}
onOpenChange={(openKeys) => {
setSubmenu(openKeys);
}}
mode="inline"
>
<Menu.Item key="1">Option 1</Menu.Item>
<Menu.Item key="2">Option 2</Menu.Item>
<SubMenu key="sub1" title="Submenu">
<Menu.Item key="3">Option 3</Menu.Item>
<Menu.Item key="4">Option 4</Menu.Item>
</SubMenu>
</Menu>
);

Conditionally rendering a child component into Header in React Native

In my react-native 0.62 app, I created an <AppHeader /> component to render the header so that I don't have to repeat the same code in every screen.
The title and burger menu are standard and always there but in some screens, I want to add one, two or more buttons to the right section -- see below:
So, it would be nice to receive and render a component on the right. If no component is received, then I wouldn't render anything and the right side would be blank.
I'm using native-base so the header understands <Left> and <Right>.
My question is how would I pass a component to my <AppHeader /> and what would the conditional part look like?
Here's my <AppHeader /> component now:
import React from 'react';
import { Header, Left, Body, Right, Button, Icon, Title } from 'native-base';
// Stylesheet
import { styles } from './style-app-header';
const AppHeader = ({ navigation, title, rightSection }) => {
return (
<Header transparent>
<Left style={{ flex: 1 }}>
<Button transparent onPress={() => navigation.navigation.openDrawer()}>
<Icon name="ios-menu" style={styles.icon} />
</Button>
</Left>
<Body style={{ flex: 1 }}>
<Title style={styles.title}>{title}</Title>
</Body>
{
rightSection === null
? <Right />
: <Right style={{ flex: 1 }}>
// How would I render the component here?
</Right>
}
</Header>
);
}
export default AppHeader;
React components can be used just like any other variable value.
const buttons = <button onClick={someAction}>Click me!</button>;
return (
<AppHeader rightSection={buttons}/>
);
// ...
<Right style={{ flex: 1 }}>
{rightSection}
</Right>
// ...

Is there a way to use <Collapse> as my Transition component while using the <Popper> component to display a Menu onHover?

The following question is regarding React and Material-UI:
I am trying to use the <Collapse> transition component when displaying my <Menu> onMouseEnter. However, there seems to be an issue in the Material-UI library when it comes to the way the <Collapse> component and the <Popper> / <Popover> component. The issue is currently open and can be seen here.
Has anyone found a good workaround for this? Basically, I am just hoping to have a subnav Menu appear when you hover over a link with this specific transition.
I have tried using the <Grow> component and the transition works just fine, but we specifically are trying to use the <Collapse> transition.
export const NavBarItem = ({ navItem }) => {
const classes = useStyles();
const [open, setOpen] = React.useState(false);
const anchorRef = React.useRef(null);
function handleToggle() {
setOpen(prevOpen => !prevOpen);
}
function handleClose(event) {
if (anchorRef.current && anchorRef.current.contains(event.target)) {
return;
}
setOpen(false);
}
return (
<React.Fragment>
<Link className={classes.link} href={BASE_HOMEPAGE + navItem.path}>
<Typography
className={classes.title}
ref={anchorRef}
aria-controls="menu-list-grow"
aria-haspopup="true"
onMouseEnter={handleToggle}
onMouseLeave={handleToggle}
>
{navItem.title}
</Typography>
</Link>
<Popper
open={open}
anchorEl={anchorRef.current}
onMouseEnter={handleToggle}
onMouseLeave={handleToggle}
transition
disablePortal
placement="bottom-start"
>
<Collapse in={open}>
<Paper id="menu-list-grow">
<ClickAwayListener onClickAway={handleClose}>
<MenuList className={classes.paperMenu}>
{navItem.menuItems.map(item => (
<Link
className={classes.link}
href={
item.external ? item.path : BASE_HOMEPAGE + item.path
}
>
<MenuItem
className={classes.paperMenuItem}
onClick={handleClose}
>
{item.text}
</MenuItem>
</Link>
))}
</MenuList>
</ClickAwayListener>
</Paper>
</Collapse>
</Popper>
</React.Fragment>
);
};
The code shown above is for a specific NavItem in a NavComponent. It is essentially just a dropdown component to show a subnav when you hover over a specific link.
Thank you for your help and please let me know if you need anymore additional information.
You can try to use the TransitionProps given by the Popper when using the transition props, as shown in the documentation
<Popper id={id} open={open} anchorEl={anchorEl} transition>
{({ TransitionProps }) => (
<Fade {...TransitionProps} timeout={350}>
<div className={classes.paper}>The content of the Popper.</div>
</Fade>
)}
</Popper>
For smoother UI you can also use the keepMounted property in Popper:
<Popper id={id} open={open} anchorEl={anchorEl} transition keepMounted>

how to use html in a material-ui Snackbar message

I'm trying (react) material-ui in my application. It's is something like the example in the docs:
function MySnackbarContentWrapper(props) {
const classes = useStyles1();
const { className, message, variant, ...other } = props;
const Icon = variantIcon[variant];
return (
<SnackbarContent
className={clsx(classes[variant], className)}
aria-describedby="client-snackbar"
message={
<span id="client-snackbar" className={classes.message}>
<Icon className={clsx(classes.icon, classes.iconVariant)} />
{message}
</span>
}
action={[
<IconButton key="close" aria-label="Close" color="inherit" onClick={props.close}>
<CloseIcon className={classes.icon} />
</IconButton>,
]}
{...other}
/>
);
}
Now, if my message text is: <em><b>Hello</b></em>, it just shows like that: <em><b>Hello</b></em>, and not like: Hello.
Can somebody help me in achieving this?
When I used angularjs in the past, and I continue to use it now, I wrapped the text in an: ng-bind-html="alert.msg | unsafe". Now, I don't now how to do that in material-ui.
Many thanks and bye ...
You can just pass the message as just text like "Hello" and provide the italics and bold styles with css to the spans
.spanClass{
font-style: italic;
font-weight: 600;
}

Resources