Google Maps - Use React to Make List Clickable - reactjs

I need to make the sidebar list clickable so when you click on a location on the sidebar, its corresponding marker will open the infowindow. Below is the code I used:
Click List function:
clickListItem = venues => {
const marker = this.state.markers.find(marker.id === venues.id);
this.handleMarkerClick(marker);
console.log(venues.name);
};
Then I tried to call it on the sidebar:
<List>
{this.props.venues &&
this.props.venues.map(({ venue }, index) => (
<ListItem
button
key={index}
onClick={() => this.props.clickListItem(this.props)}
>
<ListItemText primary={venue.name} />
</ListItem>
))}
</List>
When I click on a location, nothing happens. How do I get the list to call the marker function that opens the infowindow? Full code here.

Sidebar.js, line 154. For a start, try changing that to:
onClick={() => this.props.clickListItem(venue)}

Related

When creating a menu in a column of mui-datatable in react, it only returns the data of the last element of the list

Using the mui-datatable library in react, create a custom column using customBodyRender to add a menu and when you click on one of the options, it will perform an action.
The problem is that when you click on the action, the data that enters the function are always those of the last record in the table, regardless of selecting the menu in the first row, the data is always the last.
What I need is that when I click on the menu of a row, it returns the data of that row.
Sample code: https://codesandbox.io/s/wonderful-mclaren-ivvlq?file=/src/App.js
I've also experienced this. The way I solved it is to set the row selected index in a state variable when selecting the Menu icon, and not inside MenuItem. The Index is passed on from customBodyRenderLite or customBodyRender.
const [anchorIndex, setAnchorIndex] = useState(0);
const handleClick = (event, index) => {
setAnchorEl(event.currentTarget);
setAnchorIndex(index);
};
const iconButtonElement = (index) => {
return (
<div>
<IconButton
aria-label="More"
aria-owns={open ? "long-menu" : null}
aria-haspopup="true"
onClick={event => handleClick(event, index)}
>
<MoreVertIcon color={"action"}/>
</IconButton>
{rightIconMenu(index)}
</div>
)
}
When something should be action on the menu item, it would use the value in the state.
const rightIconMenu = () => {
return (
<Menu elevation={2} anchorEl={anchorEl} open={open} onClose={onMenuClose}>
<MenuItem onClick={handleCellClick}>View</MenuItem>
</Menu>
)
};
function handleCellClick() {
history.push('/vehicleForm', {data: currentDataSet[anchorIndex]});
}

ReactRouterHashLink not palying well with material UI drawer

I am using the packages material-ui, react-router, and react-router-hash-link. I want to have a material UI drawer (along an appbar) have hashlinks that scroll to specific bodies in the page, however whenever I do this, the scroll will happen, but when I close the drawer it reverts the scrollbar to the top of the page.
I hope you found a solution, for anybody who came across here, here is a solution:
The Drawer is expected to be closed after navigation. So, if you updated the drawer state on the onClick handler it would work as expected.
<Drawer
onClose={this.handleToggleDrawer}
anchor={"right"}
open={this.state.openDrawer}
>
<List>
{links.map(({ text, to, icon }) => (
<ListItem
onClick={this.handleToggleDrawer}
activeClassName={"Mui-selected"}
to={to}
button
key={to}
>
<ListItemIcon>{icon}</ListItemIcon>
<ListItemText primary={text} />
</ListItem>
))}
</List>
</Drawer>
handleToggleDrawer = () => {
const { openDrawer } = this.state;
this.setState({ openDrawer: !openDrawer });
}

React state is not updating when react-router-dom Link is used with material ui ListItem onClick

I have a drawer component where I put my List items in a List, on each List item click I'm navigating to respective page. I'm able to do this successfully but when I want to update state on each list item click, it is not updating on single click. I want to update my state with respective index. If I remove component & to props in ListItem, updating state is working fine. Can someone please help me in this.
const [value, setValue] = useState(0);
const handleListItemClick = (event, index) => {
setValue(index);
}
<ListItem
button
selected={selected}
onClick={event => handleListItemClick(event, 0)}
component={Link}
to={"/home"}
>
<ListItem
button
selected={selected}
onClick={event => handleListItemClick(event, 1)}
component={Link}
to={"/some-page"}
>

Material UI Nested lists using recursive render is not working with react hooks

I'm working on a project in which I need a sidebar with nested lists created with material UI, if I go to demo and copy the nested list code it's all fine but it comes with alot of code duplication. So after some digging I found recursive rendering function gist which is written with classes. I'm using react hooks and the function logic is not working as expected.
Problem:
I have 3 level navigation, A parent, then child and child contains more items (grandchildren to parent). So when I click on the parent everything is fine children items appears, but when I click any of the children element the whole list closes.
here is my Code:
// useState hook with empty object as an initial Value
const [open1, setOpen1] = React.useState({});
// this method sets the current state of a menu item i.e whether it is in expanded or collapsed or a collapsed state
const handleClick = (param) => {
setOpen1(prevState => ({[param]: !prevState[param]}));
};
// if the menu item doesn't have any child, this method simply returns a clickable menu item that redirects to any location and if there is no child this method uses recursion to go until the last level of children and then returns the item by the first condition.
function nestedMenu(items) {
return items.map((nav) => {
if (!nav.children) {
return (
<div key={nav.id}>
<ListItem button>
<ListItemText primary={nav.name} />
</ListItem>
</div>
)
}
return (
<div key={nav.id}>
<ListItem button onClick={()=>handleClick(nav.name)}>
<ListItemText primary={nav.name} />
{open1[nav.name] ? <ExpandLess /> : <ExpandMore />}
</ListItem>
<Collapse in={open1[nav.name] } timeout="auto" unmountOnExit>
<List component="div" disablePadding>
{ nestedMenu(nav.children)}
</List>
</Collapse>
</div>
)
})
}
After that I'm calling the nestedMenu function with json data as parameter in my return method
<List>
{nestedMenu(Links.items)}
</List>
Can anyone please explain what I'm doing wrong in all this, I have been working my head out to locate the problem. Any help would be much appreciated.
the problem is you change the whole open1 object :
const handleClick = (param) => {
setOpen1(prevState => ({[param]: !prevState[param]}));
};
for example if u have {p1:true, p2:false} and execute handkeClick('p1'),
open1 will be {p1:false}.
you need to keep the other members of open1 unchange and just update the one you want :
const handleClick = (param) => {
setOpen1(prevState =>
retrun {...prevState ,[param]: !prevState[param]}
);
};

Getting id from an event handler that was passed to a button component in React?

I have an App component that renders a MenuBar component. In that MenuBar, I render ListItems (from material-ui) and pass the following as a prop:
onClick = (e) => {
const id = e.target.id;
console.log(id);
console.log('called');
}
the MenuBar component:
render() {
const onClick = this.props.onClick;
const titles = ["Home", "About", "Docket", "Polls", "News"];
const listItems = titles.map(title =>
<ListItem button id={title} onClick={onClick} key={title}>
<ListItemText primary={title} />
</ListItem>);
return (
<List
component="ul"
className="menu-bar">
{listItems}
</List>
);
}
I want to use this title, which I try to retrieve from the event, so that I can render a Home component, or About component, etc, depending on which ListItem is selected. But when I run this and click randomly on some of the ListItems in my browser, the title is only logged to the console sometimes (seemingly randomly). What is the best way for me to access which ListItem was selected, or why is the console logging the title only sometimes?
Here is what I get in the browser console:
Docket
called
called
Polls
called
News
called
The reason why you don't consistently get id is that the html element triggering the click event is not always what you think. Please see this sandbox for an example. When you click on any of the ListItem, sometimes you get (if you click to the left of where the letter is, based on my trials):
<div class="MuiButtonBase-root-1883 MuiListItem-root-1871 MuiListItem-default-1874 MuiListItem-gutters-1879 MuiListItem-button-1880" tabindex="0" role="button" id="a">...</div>
where the id is present. But other times you get:
<span class="MuiTypography-root-1892 MuiTypography-subheading-1899 MuiListItemText-primary-1889">a</span>
where the id is missing.
A solution to this is to pass title directly to the onClick function:
<ListItem button id={title} onClick={() => onClick(title)}>
...
</ListItem>
Accordingly, the onClick function should be updated as follows:
onClick = (title) => {
console.log(title);
console.log('called');
}
currentTarget is what worked it for me. (instead of just target)
I've read elsewhere that maybe MUI is resulting in unexpected behavior. Similar to what Claire Lin stated, in the Material UI List (and for me, it was nested in a MUI Drawer as well), when clicking on a button, the actual target was different from what I expected. The solution I found is to use the following:
Try e.currentTarget.getAttribute('value') , where "value" is data placed on the ListItem.
Here's how I added it. See "value" being assigned, and then logged below in the onClick. (...I tried to remove most of the extra code, but there is still a bit of superfluous code in there just bc it provides context.)
return (
//removed extra code for brevity
<Drawer
anchor={'left'}
open={drawerOpen}
onClose={toggleDrawerOpen(false)}
>
<List>
{itemsList.map((item, index) => {
const { text, icon, id } = item
return (
<ListItem
button
key={id}
value={index} // <<<< HERE!!!
onClick={(e) => {
console.log(e.currentTarget.getAttribute('value')) // <<<< HERE!!!
setDrawerOpen(false)
}}
>
{icon && <ListItemIcon>{icon}</ListItemIcon>}
<ListItemText primary={text} />
</ListItem>
)
})}
</List>
</Drawer>
...Again, I used "value" and assigned it the "index".
currentTarget is the trick.

Resources