Material-UI: ListItem onClick not called - reactjs

I am working with React and Material-UI. I am trying to display a list and call a function when one of the items of the list is clicked.
The code below is a simplified version of my code, but it should contain all the lines concerning the issue.
The onClick function is apparently never called. What am I missing?
App.js:
import React, { Component } from 'react';
import './App.css';
import Grid from '#material-ui/core/Grid';
import Map from './Map.js';
class App extends Component {
render() {
return (
<div >
<Grid container spacing={24}>
<Grid item xs={3}>
Column text
</Grid>
<Grid item xs={9}>
<Map/>
</Grid>
</Grid>
</div>
);
}
}
export default App;
Map.js:
import React from 'react';
import List from '#material-ui/core/List';
import ListItem from '#material-ui/core/ListItem';
import ListItemText from '#material-ui/core/ListItemText';
class Map extends React.Component {
constructor(props) {
super(props);
this.state = {
sensorsList: {
isLoaded: false,
data: null,
},
};
}
componentDidMount() {
// retrieve list of sensors
fetch("https://api-of-things.plenar.io/api/sensors?size=10000")
.then(res => res.json())
.then(
(result) => {
this.setState({
sensorsList: {
isLoaded: true,
data: Object.keys(result.data).map(key => result.data[key].path),
}
});
},
// Note: it's important to handle errors here
// instead of a catch() block so that we don't swallow
// exceptions from actual bugs in components.
(error) => {
this.setState({
error
});
}
)
}
selectSensor(name) {
console.log(name);
}
_renderSensorsList() {
const {sensorsList} = this.state;
return sensorsList.isLoaded && (
<div style={{
position: 'absolute',
zIndex: 1,
pointerEvents: 'none',
right: 10,
top: 10,
backgroundColor: 'white',
}}>
<List component="nav">
{ sensorsList.data.map(key =>
<ListItem button key={key} onClick={() => this.selectSensor("ciao")} >
<ListItemText primary={key} />
</ListItem>
)}
</List>
</div>
);
}
render() {
const {sensorsList, selectedSensor} = this.state;
return (
<div>
{ this._renderSensorsList() }
</div>
);
}
}
export default Map;

The problem is that in your div's style you are setting pointerEvents: 'none', preventing the click to reach the DOM event listener, remove it and it will work.
<div style={{
position: 'absolute',
zIndex: 1,
pointerEvents: 'none', //<---- remove this line
right: 10,
top: 10,
backgroundColor: 'white',
}}>

try replacing this
_renderSensorsList() {
with arrow function like this
_renderSensorsList = () => {

Related

React Select with avatar class component whats wrong here select not populating

Hi I had working select box with avatar on functional aporx. But I need build in functions to change selectbox properties like hidden: true/false, update option data function to add new option data to display selectbox with certain values on fly.
What I wrong here? Render part works as tested with functional version. The class factoring misses something as select box does not get info ether options and avatar to display and no width calculation happening.
Orginal functional code: https://codesandbox.io/s/react-select-longest-option-width-geunu?file=/src/App.js
Class based works but nodatin selectbox. Here is app.js with select.js fiddle: https://codesandbox.io/s/react-select-longest-option-width-forked-plqq0p?file=/src/Select.js
Source:
import React, { useRef } from "react";
import Select from "react-select";
class RtSelect extends React.Component {
constructor(props) {
super();
this.state = {
info: props.info,
options: props.options,
hidden: props.hidden,
menuIsOpen: false,
menuWidth: "",
IsCalculatingWidth: false
};
this.selectRef = React.createRef();
this.onMenuOpen = this.onMenuOpen.bind(this);
}
componentDidMount() {
if (!this.menuWidth && !this.isCalculatingWidth) {
setTimeout(() => {
this.setState({IsCalculatingWidth: true});
// setIsOpen doesn't trigger onOpenMenu, so calling internal method
this.selectRef.current.select.openMenu();
this.setState({MenuIsOpen: true});
}, 1);
}
}
onMenuOpen() {
if (!this.menuWidth && this.isCalculatingWidth) {
setTimeout(() => {
const width = this.selectRef.current.select.menuListRef.getBoundingClientRect()
.width;
this.setState({menuWidth: width});
this.setState({IsCalculatingWidth: false});
// setting isMenuOpen to undefined and closing menu
this.selectRef.current.select.onMenuClose();
this.setState({MenuIsOpen: true});
}, 1);
}
}
styles = {
menu: (css) => ({
...css,
width: "auto",
...(this.isCalculatingWidth && { height: 0, visibility: "hidden" })
}),
control: (css) => ({ ...css, display: "inline-flex " }),
valueContainer: (css) => ({
...css,
...(this.menuWidth && { width: this.menuWidth })
})
};
setData (props) {
this.setState({
info: props.info,
options: props.options,
hidden: props.hidden
})
}
render() {
return (
<div style={{ display: "flex" }}>
<div style={{ margin: "8px" }}>{this.info}</div>
<div>
<Select
ref={this.selectRef}
onMenuOpen={this.onMenuOpen}
options={this.options}
menuIsOpen={this.menuIsOpen}
styles={this.styles}
isDisabled={this.hidden}
formatOptionLabel={(options) => (
<div className="select-option" style={{ display: "flex" }}>
<div style={{ display: "inline", verticalAlign: "center" }}>
<img src={options.avatar} width="30px" alt="Avatar" />
</div>
<div style={{ display: "inline", marginLeft: "10px" }}>
<span>{options.label}</span>
</div>
</div>
)}
/>
</div>
</div>
);
}
}
export default RtSelect;
Got it working!
I had removed "undefined" from onOpen setState function. I compared those 2 fiddles and finally got it working.
// setting isMenuOpen to undefined and closing menu
this.selectRef.current.select.onMenuClose();
this.setState({MenuIsOpen: undefined});

how to show 10 data when I am scrolling down Its just show next 10 data in react js?

When I am using scroll down so that time our function "fetchMoreData"?
I want to scroll down that time my function is called
const fetchMoreData = () =>{
console.log("pulkit")
}
<InfiniteScroll
dataLength={25}
next={fetchMoreData}
hasMore={true}
loader={<h4>Loading...</h4>}>
<Grid container spacing={4} sx={{ marginTop: '1rem' }}>
{simulationList.map((item, i) => (
<Grid
item
xs={3}
key={item?._id}
>
</Grid>
))}
</Grid>
</InfiniteScroll>
Try using the different scroll libraries of functions to scroll in react.
for my code, i have been using this "react-scroll-wheel-handler" which allows me to display only the required number of items on the screen and even allows me to change the setting in the UI where i can change the number of results in the output table.
https://www.npmjs.com/package/react-scroll-wheel-handler
I've tried to recreate your scenario.It's from react-infinite-scroll-component
example.. Try this out
Sandbox code
you don't need any lib you can do using it to react onScroll event pls find the working demo here
import React from "react";
import { render } from "react-dom";
const style = {
height: 30,
border: "1px solid green",
margin: 6,
padding: 8
};
class App extends React.Component {
state = {
items: Array.from({ length: 20 })
};
fetchMoreData = () => {
console.log("pulkit");
setTimeout(() => {
this.setState({
items: this.state.items.concat(Array.from({ length: 20 }))
});
}, 1500);
};
onHandleScroll = (e) => {
e.persist();
if (e.target.scrollHeight - e.target.scrollTop === e.target.clientHeight) {
this.fetchMoreData()
}
}
render() {
return (
<div onScroll={this.onHandleScroll} style={{
overflow: "scroll", height: '800px'
}}>
<h1>demo: react-infinite-scroll-component</h1>
<hr />
{this.state.items.map((i, index) => (
<div style={style} key={index}>
div - #{index}
</div>
))}
</div>
);
}
}
render(<App />, document.getElementById("root"));

How would I open a modal to allow a user to select what component to add?

I have a react app that creates a widget layout where they can add and remove widgets in a grid of 4. Currently in the addEvent I have it defaulted to add the "DataTable" component.Instead, I want it to open a modal from which they can select from the "DataTable" or "CheckboxList" component and a larger list of components later on. I am new to react and not exactly sure how to implement this, any help would be great.
import React, { Component } from 'react';
import Swappable from './components/SwappableComponent'
import './App.css';
import DataTable from './components/tableWidget';
import CheckboxList from './components/CheckboxList';
import PropTypes from "prop-types";
import { withStyles } from "#material-ui/core/styles";
import Paper from "#material-ui/core/Paper";
import Grid from "#material-ui/core/Grid";
const styles = theme => ({
root: {
flexGrow: 1
},
paper: {
padding: theme.spacing.unit * 2,
textAlign: "center",
color: theme.palette.text.secondary
}
});
class App extends Component {
constructor(props) {
super(props);
this.state={
widgets:[
{id:1, content: <DataTable/>},
{id:2, content: <CheckboxList/>},
{id:3, content: ""},
{id:4, content: ""}
]
}
}
deleteEvent=(index)=>{
const copyWidgets=Object.assign([],this.state.widgets);
let widget=this.state.widgets[index];
widget.content="";
copyWidgets[index]=widget;
this.setState({
widgets:copyWidgets
})
}
addEvent=(index)=>{
const copyWidgets=Object.assign([],this.state.widgets);
let widget=this.state.widgets[index];
widget.content=<DataTable/>;
copyWidgets[index]=widget;
this.setState({
widgets:copyWidgets
})
}
render() {
const { classes } = this.props;
return (
<div className={classes.root}>
<Grid container spacing={24}>
{
this.state.widgets.map((widget,index)=>{
return(
<Grid item xs={12} sm={6}>
<Paper className={classes.paper}><Swappable id={widget.id} content={widget.content} delete={this.deleteEvent.bind(this,index)} add={this.addEvent.bind(this,index)}/></Paper>
</Grid>
)
})
}
</Grid>
</div>
);
}
}
App.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles(styles)(App);
The basics of a modal component is below. You can add header and footer sections, fade-in effects, opacity on background etc - go crazy
class Modal extends React.Component {
render() {
const { display, close, children } = this.props;
if (!display) return null;
return (
<div className="modal">
{children}
<button onClick={close}>Close</button>
</div>
)
}
}
// css
.modal {
position: fixed;
top: 10%;
width: 90%;
height: 90%;
}
// use it
<Modal display={this.state.displayModal}
close={()=>this.setState({displayModal: false})} >
// add your modal content here
<h1>Add Event</h1>
<p>Some relevant jsx here</p>
</Modal>
to initiate the modal you just set displayModal to true:
addEvent = () => {
this.setState({displayModal:true});
}

React Bootstrap OverlayTrigger not rearranging after popover content changes

I have an issue when refreshing the content of a Popover using the OverlayTrigger. Basically, what I would expect is that if the content changes, the OverlayTrigger rearranges its position. But it doesn't.
Given the following code, that can be seen here: https://codesandbox.io/s/W6pDkDoyW
import React from 'react';
import { render } from 'react-dom';
import { Popover, OverlayTrigger } from 'react-bootstrap';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
names: ['george'],
};
this.loadMore = this.loadMore.bind(this);
this.setOld = this.setOld.bind(this);
}
loadMore() {
const _this = this;
setTimeout(() => {
_this.setState({ names: ['george', 'steve', 'peter'] });
}, 500);
}
setOld() {
this.setState({ names: ['george'] });
}
render() {
const popover = (
<Popover id="test-popover">
{this.state.names.map((n, index) =>
<p key={index}>
{n}
</p>,
)}
</Popover>
);
return (
<OverlayTrigger
trigger={['hover', 'focus']}
placement="top"
overlay={popover}
onEnter={this.loadMore}
onExit={this.setOld}
>
<span>This is a div</span>
</OverlayTrigger>
);
}
}
const Container = () => {
return (
<div
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
minHeight: '24em',
}}
>
<div style={{ maxWidth: '50%' }}>
<App />
</div>
</div>
);
};
render(<Container />, document.getElementById('root'));
Is this possible or not?

react-burger-menu css does not work

I'm using burger-menu and i can't set CSS for the burger menu like the author guide: https://github.com/negomi/react-burger-menu
Here's my burger menu component:
import React from 'react';
import BurgerMenu from 'react-burger-menu';
import { List, ListItem, ListItemContent } from 'react-mdl';
var MenuWrap = React.createClass({
getInitialState() {
return {hidden : false};
},
toggle() {
this.setState({hidden: !this.state.hidden});
},
render() {
let style;
if (this.state.hidden) {
style = {display: 'none'};
}
return (
<div style={style} className={this.props.side}>
{this.props.children}
</div>
);
}
});
export default class LeftSidebar extends React.Component {
constructor(props) {
super(props);
this.state = {
currentMenu: 'push',
side: 'left',
hidden: true,
};
};
render() {
const Menu = BurgerMenu[this.state.currentMenu];
var styles = {
bmBurgerButton: {
position: 'fixed',
width: '36px',
height: '30px',
left: '36px',
top: '36px'
},
bmBurgerBars: {
background: '#373a47'
},
bmCrossButton: {
height: '24px',
width: '24px'
},
bmCross: {
background: '#bdc3c7'
},
bmMenu: {
background: '#373a47',
padding: '2.5em 1.5em 0',
fontSize: '1.15em'
},
bmMorphShape: {
fill: '#373a47'
},
bmItemList: {
color: '#b8b7ad',
padding: '0.8em'
},
bmOverlay: {
background: 'rgba(0, 0, 0, 0.3)'
}
};
return (
<MenuWrap wait={20}>
<Menu
style={styles}
noOverlay id={this.state.currentMenu}
pageWrapId={'page-wrap'}
outerContainerId={'outer-container'}
>
{console.log(Menu)}
<List>
<ListItem>
<ListItemContent icon="person">Dashboard</ListItemContent>
</ListItem>
<ListItem>
<ListItemContent icon="person">Community</ListItemContent>
</ListItem>
<ListItem>
<ListItemContent icon="person">About</ListItemContent>
</ListItem>
</List>
</Menu>
</MenuWrap>
);
}
};
And here is my main component:
import React from 'react';
import styles from './Main.scss';
import LeftSidebar from '../LeftSidebar/LeftSidebar'
export default class Program extends React.Component {
render() {
return (
<div id="outer-container" style={{height: '100%'}}>
<LeftSidebar />
<div id="page-wrap">
<p>Content</p>
</div>
</div>
);
}
}
All of the css from variable styles does not work.
EDIT: the problem above is solved by change style ={styles} to styles = {styles}. The other problem is: when i click close, the sidebar menu shift down about 10 or 20px before moving back to the left. How to remove that shift down effect?
Seems like you have a typo. It should be styles={styles} instead of style={styles}.

Resources