Can't remove scrollbar from Material UI Dialog - javascript

I have a modal window with a keyboard in it. Everything's fine, except that I can't remove the scrollbar. I tried adding overflow:'hidden' as inline css but still nothing.
Also, even when using container-full padding-0 in bootstrap, the components still won't go till the edge of the screen. So I guess here's the problem.
This is where I render my component
<div className="container-full padding-0">
<div className="row">
<div className="col-sm-3">
<ButtonsGrid list={this.state.list} clicked={this.clicked}/>
</div>
<div className="col-sm-3" style={{paddingLeft:0, paddingRight:0}}>
<ButtonsGrid list = {this.state.list} clicked={this.clicked}/>
</div>
<div className="col-sm-6" style={{paddingRight: 0, paddingLeft: 0}}>
<Keyboard search={this.search}/> <-------------- HERE
</div>
</div>
</div>
And the component's render looks like this:
render() {
return(
<div>
<Paper
onClick={this.toggleKeyboard}>
<p
style={{
fontSize:40,
overflow:'hidden'}}>
{this.state.input !== '' ?
this.state.input : 'Search...'}
</p>
</Paper>
<br />
{this.state.showKeyboard ?
<Dialog
open={this.state.showKeyboard}
maxWidth='md'fullWidth>
<GridList
cellHeight={50}
cols={11}
style={{overflowX:'hidden'}}>
{this.state.keyboard.length > 0 ?
this.state.keyboard.map(key => {
return(
<Button
disabled={key.value === ''}
key={Math.random()*13}
style={{minWidth: '30px', border: '1px solid'}}
color="default"
onClick={key.value !== 'Enter' ?
() => this.onInputChanged(key.value) :
() => this.search(key.value)}>
<div
style={{fontSize:'15px',
display: 'flex',
justifyContent: 'center',
textAlign:'center'}}
>
{key.value}
</div>
</Button>
)
}):null}
</GridList>
</Dialog>:''}
</div>
);
}
Also, here's a visual.
If I inspect the element in the browser, I can just uncheck overflow and it removes it.
I tried adding overflow:'hidden' to the div where the component gets rendered but it still wouldn't work.
Any ideas?

Just set overflow on DialogContent:
<Dialog
fullWidth={true}
maxWidth="xl"
open={this.state.isChartOpen}
onClose={() => this.setState({ isChartOpen: false })}
>
<DialogContent style={{ overflow: "hidden" }}>
<ContractPriceChart contracts={this.props.contracts} />
</DialogContent>
</Dialog>

Inside your sx property add:
'&::-webkit-scrollbar': {display: none}

I solved this problem in functional component in following code.
You should manipulate the overflow attribute of "< html >" tag.
When isOpen is true it will add "overflow-hidden" class to the html tag.
And when isOpen is false, it will remove the "overflow-hidden" class from the html tag.
import React, { useEffect } from 'react';
import Dialog from '#material-ui/core/Dialog';
import DialogContent from '#material-ui/core/DialogContent';
const MyDialog = (props) => {
const { isOpen } = props;
useEffect(() => {
const htmlElement = document.querySelector('html');
if (isOpen && !htmlElement.classList.contains('overflow-hidden')) {
htmlElement.classList.add('overflow-hidden');
} else {
htmlElement.classList.remove('overflow-hidden');
}
}, []);
useEffect(() => {
const htmlElement = document.querySelector('html');
if (isOpen && !htmlElement.classList.contains('overflow-hidden')) {
htmlElement.classList.add('overflow-hidden');
} else {
htmlElement.classList.remove('overflow-hidden');
}
}, [isOpen]);
return (
<div>
<Dialog
open={isOpen}
maxWidth="xl"
>
<DialogContent>
Content 1
Content 2
</DialogContent>
</Dialog>
</div>
);
};
And add this class to your global style.
.overflow-hidden {
overflow: hidden !important;
}

have you tried adding !important? like this: overflow:'hidden !important'

put all dialog element in <Dialog><DialogContent>.....</DialogContent></Dialog>

put all dialog element in <Dialog><DialogContent>.....</DialogContent></Dialog>here code:
render() {
return(
<div>
<Paper
onClick={this.toggleKeyboard}>
<p
style={{
fontSize:40,
overflow:'hidden'}}>
{this.state.input !== '' ?
this.state.input : 'Search...'}
</p>
</Paper>
<br />
{this.state.showKeyboard ?
<Dialog
open={this.state.showKeyboard}
maxWidth='md'fullWidth>
<GridList
cellHeight={50}
cols={11}
style={{overflowX:'hidden'}}>
<DialogContent>
{this.state.keyboard.length > 0 ?
this.state.keyboard.map(key => {
return(
<Button
disabled={key.value === ''}
key={Math.random()*13}
style={{minWidth: '30px', border: '1px solid'}}
color="default"
onClick={key.value !== 'Enter' ?
() => this.onInputChanged(key.value) :
() => this.search(key.value)}>
<div
style={{fontSize:'15px',
display: 'flex',
justifyContent: 'center',
textAlign:'center'}}
>
{key.value}
</div>
</Button>
)
}):null}
</GridList>
</DialogContent>
</Dialog>:''}
</div>
);
}

Try utilizing the pseudo element -webkit-scrollbar to remove it:
.MuiDialog-paper::-webkit-scrollbar {
display: none;
}
if it doesn't work you can try:
.MuiDialog-root::-webkit-scrollbar {
display: none;
}
The downside is that you can't use it inline, but I tested here it works.

you can try with this:
<DialogContent className={classes.hiddenScroll}>
and their styles:
const useStyles = makeStyles(theme => ({
hiddenScroll: {
overflow: 'hidden',
},

I was using Material-ui Backdrop faced the same issue. Tried Fatih Turgut approach with a slight difference
import React, { useEffect, useState } from 'react';
import { Backdrop } from '#material-ui/core';
import { makeStyles } from '#material-ui/core';
const useStyles = makeStyles({
paper: {
zIndex: 20,
},
});
function Example() {
const [open, setOpen] = useState(true);
useEffect(() => {
const htmlElement = document.querySelector('body');
if (open || !htmlElement.classList.contains('overflow-hidden')) {
htmlElement.classList.add('overflow-hidden');
} else {
htmlElement.classList.remove('overflow-hidden');
}
}, [open]);
const classes = useStyles();
const handleOpen = open => {
setOpen(open);
};
return (
<Backdrop
className={classes.paper}
open={open}
onClick={() => handleOpen(!open)}
>
<h1>hello</h1>
</Backdrop>
);
}
export default Example;

Related

How do I set autofocus to an input that's inside a select dropdown?

I have an input field inside a select dropdown. I need to focus on that input box as soon as the dropdown is shown when the user clicks on it. I tried using refs, but that doesn't seem to work. I'm using antd 3.26.14 and React 16.8.6. Here is the code:
<Select
labelInValue
open={isOpenSelectCategory}
onDropdownVisibleChange={onDropdownVisibleChange}
placeholder="Select Category"
onChange={() => {
searchDropdownOptions('formCategories', '');
setCategoryInputValue('');
}}
notFoundContent={null}
dropdownRender={menu => (
<>
<div
onMouseDown={lockSelectCategoryClose}
onMouseUp={lockSelectCategoryClose}
style={{ marginBottom: '10px' }}
>
<Input
value={categoryInputValue}
ref={inputRef}
onChange={event => {
searchDropdownOptions(
'formCategories',
event.target.value,
);
setCategoryInputValue(event.target.value);
}}
placeholder="Search category or create new one"
/>
...
The useEffect for the Input ref:
useEffect(() => {
if (inputRef.current) inputRef.current.focus();
}, [inputRef]);
I've tried variations of the above useEffect, where instead of listening to changes on inputRef, I've listened to the change when the dropdown gets loaded. Neither of them worked though.
Any help here will be much appreciated...
Try to use ref={(input) => input && input.focus()} in combination with autofocus property e.g.:
<Input
autofocus
ref={(input) => input && input.focus()}
...
/>
Here is a working stackblitz for a react class component.
NOTE: The issue with this solution is that it focuses input on any re-render (which might not be desired).
See also how-to-set-focus-on-an-input-field-after-rendering for more options.
Code for the linked complete example:
import React, { useFocus } from 'react';
import ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import './index.css';
import { Select, Divider, Input } from 'antd';
import { PlusOutlined } from '#ant-design/icons';
const { Option } = Select;
let index = 0;
class App extends React.Component {
state = {
items: ['jack', 'lucy'],
name: '',
};
onNameChange = (event) => {
this.setState({
name: event.target.value,
});
};
addItem = () => {
console.log('addItem');
const { items, name } = this.state;
this.setState({
items: [...items, name || `New item ${index++}`],
name: '',
});
};
render() {
// const [inputRef, setInputFocus] = useFocus();
const { items, name } = this.state;
return (
<Select
style={{ width: 240 }}
placeholder="custom dropdown render"
dropdownRender={(menu) => (
<div>
{menu}
<Divider style={{ margin: '4px 0' }} />
<div style={{ display: 'flex', flexWrap: 'nowrap', padding: 8 }}>
<Input
autofocus
ref={(input) => input && input.focus()}
style={{ flex: 'auto' }}
value={name}
onChange={this.onNameChange}
/>
<a
style={{
flex: 'none',
padding: '8px',
display: 'block',
cursor: 'pointer',
}}
onClick={this.addItem}
>
<PlusOutlined /> Add item
</a>
</div>
</div>
)}
>
{items.map((item) => (
<Option key={item}>{item}</Option>
))}
</Select>
);
}
}
ReactDOM.render(<App />, document.getElementById('container'));

Switch function in react component not working as logic would suggest

So my react code does not execute as logic would suggest:
I am trying to create a page that resembles an email app.
I have components in React which I import into my message(main) component (e.g. Inbox component, send mail component etc). I have a useState, which is set to 'inbox' as default and a switch statement which checks which value is in the state and returns the component matching that case. I also have a onclick function which changes the state value based on which email tab you want to view (e.g. Inbox or trash etc). When the state changes the component should run the switch statement in my page render and display the correct component in the main component, which is does most of the time.
My problem comes when I keep switching between the tabs which have components it at some point goes to the default of the switch statement which does not make sense because either of the values should have passed.
Please help
import React, {useState} from 'react';
// Components to be displayed
import Inbox from './Inbox';
import SendMessage from './SendMessage';
// Other components on the page which you can ignore
import Navbar from '../Layout/Navbar';
import Copyright from '../Layout/Copyright';
import SendMail from './SendMail';
//Material ui for styling
import AppBar from '#material-ui/core/AppBar';
import CssBaseline from '#material-ui/core/CssBaseline';
import Divider from '#material-ui/core/Divider';
import Drawer from '#material-ui/core/Drawer';
import Hidden from '#material-ui/core/Hidden';
import IconButton from '#material-ui/core/IconButton';
import InboxIcon from '#material-ui/icons/MoveToInbox';
import List from '#material-ui/core/List';
import ListItem from '#material-ui/core/ListItem';
import ListItemIcon from '#material-ui/core/ListItemIcon';
import ListItemText from '#material-ui/core/ListItemText';
import MailIcon from '#material-ui/icons/Mail';
import { makeStyles, useTheme } from '#material-ui/core/styles';
import Link from '#material-ui/core/Link';
import ControlPointIcon from '#material-ui/icons/ControlPoint';
const drawerWidth = 240;
const list = [
{id: 1, title: 'Singing lessons', message: 'We are practicing at 5:00'},
{id: 2, title: 'Meeting', message: 'Hi Guys, we can meet during lunch at Nandos'},
{id: 3, title: 'New Product release', message: 'Hi guys, we are encouraging everyone to buy in on the new product'}
]
const useStyles = makeStyles((theme) => ({
root: {
display: 'flex'
},
drawer: {
[theme.breakpoints.up('sm')]: {
width: drawerWidth,
flexShrink: 0,
zIndex: '0'
}
},
appBar: {
[theme.breakpoints.up('sm')]: {
width: `calc(100% - ${drawerWidth}px)`,
marginLeft: drawerWidth,
},
},
menuButton: {
marginRight: theme.spacing(2),
[theme.breakpoints.up('sm')]: {
display: 'none',
},
},
// necessary for content to be below app bar
toolbar: theme.mixins.toolbar,
drawerPaper: {
width: drawerWidth,
},
content: {
flexGrow: 1,
padding: theme.spacing(3)
},
listItemStyle: {
marginTop: '50px'
},
newMessage: {
fontSize: '40px',
backgroundColor: '#64b5f6',
borderRadius: '50px',
color: '#fff',
position: 'absolute',
bottom: '50px',
right: '50px',
'&:hover': {
backgroundColor: '#1976d2'
}
}
}));
// Main component
const Message = (props) => {
const { window } = props;
const classes = useStyles();
const theme = useTheme();
const [mobileOpen, setMobileOpen] = useState(false);
const [tabTracker, setTabTracker] = useState('Inbox');
const renderSwitch = (param) => {
switch(param) {
case 'Inbox':
return <Inbox />;
case 'Send email':
return <SendMail />;
case 'Drafts':
return 'Draft';
case 'Trash':
return 'Trash';
case 'Spam':
return 'Spam';
case 'newMessage':
return <SendMessage />;
default:
return 'foo';
}
}
const tabControl = (e) => {
setTabTracker(e.target.firstChild.data);
//renderSwitch(tabTracker);
}
const newMsg = (e) => {
setTabTracker(e.target.attributes[5].value);
//renderSwitch(tabTracker);
}
const handleDrawerToggle = () => {
setMobileOpen(!mobileOpen);
};
const drawer = (
<div>
<div className={classes.toolbar} />
<Divider />
<List className={classes.listItemStyle}>
{['Inbox', 'Send email', 'Drafts'].map((text, index) => (
<ListItem button key={text} onClick={tabControl}>
<ListItemIcon>{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}</ListItemIcon>
<ListItemText primary={text} />
</ListItem>
))}
</List>
<Divider />
<List>
{['Trash', 'Spam'].map((text, index) => (
<ListItem button key={text} onClick={tabControl}>
<ListItemIcon>{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}</ListItemIcon>
<ListItemText primary={text} />
</ListItem>
))}
</List>
</div>
);
const container = window !== undefined ? () => window().document.body : undefined;
return (
<React.Fragment>
<span>
<Navbar />
</span>
<div className={classes.root}>
<CssBaseline />
<nav className={classes.drawer} aria-label="mailbox folders">
{/* The implementation can be swapped with js to avoid SEO duplication of links. */}
<Hidden smUp implementation="css">
<Drawer
container={container}
variant="temporary"
anchor={theme.direction === 'rtl' ? 'right' : 'left'}
open={mobileOpen}
onClose={handleDrawerToggle}
classes={{
paper: classes.drawerPaper,
}}
ModalProps={{
keepMounted: true, // Better open performance on mobile.
}}
>
{drawer}
</Drawer>
</Hidden>
<Hidden xsDown implementation="css">
<Drawer
classes={{
paper: classes.drawerPaper,
}}
variant="permanent"
open
>
{drawer}
</Drawer>
</Hidden>
</nav>
<main className={classes.content}>
<div className={classes.toolbar} />
{renderSwitch(tabTracker)}
<Link href="#">
<ControlPointIcon value="newMessage" primary="newMessage" className= {classes.newMessage} onClick={newMsg} />
</Link>
</main>
</div>
<Copyright />
</React.Fragment>
);
}
// ResponsiveDrawer.propTypes = {
// /**
// * Injected by the documentation to work in an iframe.
// * You won't need it on your project.
// */
// window: PropTypes.func,
// };
export default Message;
e.target gives you the element on which click was actually triggered, so when you have multiple elements as children within ListItem, its possible that you would have clicked on ListItemIcon and hence e.target is listItemIcon which was not your intention as it will give you an incorrect value for e.target.firstChild.data
So you could either use e.currentTarget which will give you the element on which the onClick listener is attached or you could simply pass on the information to tabControl by using an inline arrow function
const tabControl = (value) => {
setTabTracker(value);
}
const drawer = (
<div>
<div className={classes.toolbar} />
<Divider />
<List className={classes.listItemStyle}>
{['Inbox', 'Send email', 'Drafts'].map((text, index) => (
<ListItem button key={text} onClick={() => tabControl(text)}>
<ListItemIcon>{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}</ListItemIcon>
<ListItemText primary={text} />
</ListItem>
))}
</List>
<Divider />
<List>
{['Trash', 'Spam'].map((text, index) => (
<ListItem button key={text} onClick={() => tabControl(text)}>
<ListItemIcon>{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}</ListItemIcon>
<ListItemText primary={text} />
</ListItem>
))}
</List>
</div>
);

`TypeError: Cannot read property 'sportId' of undefined`

I need to hide the button.
Its working fine in Class based code.
but when I convert to react hooks its throwing an error
TypeError: Cannot read property 'sportId' of undefined
I researched and followed below links steps.10 Steps to Convert React Class Component to React Functional Component with Hooks
but still not helping me.
can you tell me how to fix it.
providing my code snippet below
React hooks
import React, { useState } from 'react'
import SimpleTabs from './components/SimpleTabs/index';
import Button from '#material-ui/core/Button';
import SideNav from '../SideNav';
import '../../styles.css';
import { withStyles } from '#material-ui/core/styles';
const World = () => {
const [sportId, setEmail] = useState(window.sessionStorage.getItem('includeFish'));
const [password, setPassword] = useState('');
const handleSubmit = event => {
event.preventDefault();
// console.log(email);
// console.log(password);
}
return (
<div>
<SideNav />
<div className="World-dockRightContainer">
<div className="World-heading">
Research and World
<div className="World-button-container">
<Button
variant="outlined"
color="primary"
size="small"
className="World-button-World"
style={{
//display: this.state.paperSelected
display: this.state.sportId
? 'none'
: '',
}}
>
World Fish
</Button>
<Button
variant="outlined"
color="primary"
size="small"
className="World-button-World--active"
// disabled={this.state.disableWorldFish}
style={{
//display: this.state.paperSelected
display: !this.state.sportId
? 'none'
: '',
}}
>
World Fishing(1)
</Button>
</div>
</div>
<SimpleTabs />
</div>
</div>
)
};
export default World;
class based
import React, { Component } from 'react'; //useState,
import SimpleTabs from './components/SimpleTabs/index';
import Button from '#material-ui/core/Button';
import SideNav from '../SideNav';
import '../../styles.css';
import { withStyles } from '#material-ui/core/styles';
import { connect } from 'react-redux';
import {
reduxForm,
} from 'redux-form';
//import { WorldActions } from '../../../../actions';
//function World() {
class World extends Component {
state = {
paperSelected: false,
data: '',
disableWorldFish: true,
sportId: window.sessionStorage.getItem('includeFish')
};
componentWillReceiveProps(nextprops) {
console.log('index componentWillReceiveProps obj3 -->', nextprops.paperSelected);
}
componentDidMount() {
let { data } = this.props;
this.setState({ paperSelected: this.props.paperSelected });
}
render() {
//let sportId = window.sessionStorage.getItem('includeFish');
//return (
return <div>
<SideNav />
<div className="World-dockRightContainer">
<div className="World-heading">
Research and World
<div className="World-button-container">
<Button
variant="outlined"
color="primary"
size="small"
className="World-button-World"
style={{
//display: this.state.paperSelected
display: this.state.sportId
? 'none'
: '',
}}
>
World Fish
</Button>
<Button
variant="outlined"
color="primary"
size="small"
className="World-button-World--active"
// disabled={this.state.disableWorldFish}
style={{
//display: this.state.paperSelected
display: !this.state.sportId
? 'none'
: '',
}}
>
World Fishing(1)
</Button>
</div>
</div>
<SimpleTabs />
</div>
</div>;
}
//);
}
export default World;
In the hook example you forgot to update the line where you are using the variable
display: !this.state.sportId
needs to simply be
display: !sportId
Your problem is here,
style={{
//display: this.state.paperSelected
display: this.state.sportId
? 'none'
: '',
}}
and here,
style={{
//display: this.state.paperSelected
display: !this.state.sportId
? 'none'
: '',
}}
In function component you don't have access to this, you need to change them to this,
style={{ display: sportId ? 'none' : ''}}
and this,
style={{ display: !sportId ? 'none' : ''}}

How to implement drag and drop behaviour in React

I'm trying to implement drag and drop behaviour using React and react-beautiful-dnd library.
I want to chose some images using react-dropzone library and after choosing images I show thumbnails on the right side of the screen and after that I want to be able to drag one of those thumbnails to the left side and drop it to one of those containers.
My code is as follows:
import React, { Component } from "react";
import ReactDOM from "react-dom";
import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd";
import Dropzone from "react-dropzone";
import { Animated } from "react-animated-css";
import { orderBy } from "lodash";
import UUID from "uuid";
import "./styles.css";
const animationIn = "fadeInDown";
const animationOut = "fadeOutUp";
const animationDuration = 400; // in ms
const pictureTypes = [
{
title: "3/4 front left",
imageOverlay: "https://via.placeholder.com/100",
item: "front-left",
mandatory: true,
image: null,
priority: 1
},
{
title: "3/4 rear right",
imageOverlay: "https://via.placeholder.com/100",
item: "rear-right",
mandatory: true,
image: null,
priority: 2
},
{
title: "Inside door right",
imageOverlay: "https://via.placeholder.com/100",
item: "front-door-right-i",
mandatory: true,
image: null,
priority: 3
}
];
class App extends Component {
constructor(props) {
super(props);
this.state = {
files: [],
pictureTypes: pictureTypes
};
this.onDragEnd = this.onDragEnd.bind(this);
}
onDragEnd(result) {
debugger;
// dropped outside the list
if (!result.destination) {
return;
}
}
addFilesToState(files) {
let files_with_preview = [];
files.map(file => {
file["preview"] = URL.createObjectURL(file);
files_with_preview.push(file);
this.setState({ [`visibleAnimate${file.path}`]: true });
});
const new_files = [...this.state.files, ...files_with_preview];
this.setState({ files: new_files });
}
renderPreviews(files) {
if (files.length < 1)
return <div>Drag and drop some files to see them here.</div>;
return (
<div style={{ display: "flex", flexDirection: "column" }}>
<div>Chosen pictures</div>
<div style={{ display: "flex", flexDirection: "row" }}>
{files.map((file, index) => {
return (
<Draggable key={UUID.v4()} draggableId={UUID.v4()} index={index}>
{provided => (
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
>
<img
src={file.preview}
alt={file.path}
style={{ width: 80 }}
/>
</div>
)}
</Draggable>
);
})}
</div>
</div>
);
}
handlePictureTypesDrop(file, pictureType) {
const file_blob = URL.createObjectURL(file);
const updated_picture_type = {
...this.state.pictureTypes.find(pt => pt.item === pictureType.item),
image: file_blob
};
const updated_picture_types = [
...this.state.pictureTypes.filter(pt => pt.item !== pictureType.item),
updated_picture_type
];
let new_picture_types = [...updated_picture_types];
this.setState({ pictureTypes: new_picture_types });
}
renderPictureTypes() {
const { allowed_types } = this.props;
const { pictureTypes } = this.state;
const self = this;
return orderBy(pictureTypes, "priority").map(pt => {
return (
<div style={{ width: "25%", marginRight: 5 }}>
<Dropzone
onDrop={files => self.handlePictureTypesDrop(files[0], pt)}
accept={allowed_types}
multiple={false}
>
{({ getRootProps, getInputProps }) => (
<div {...getRootProps()}>
<input {...getInputProps()} />
<div className="picture-types-wrapper">
<div>
<img
src={pt.image !== null ? pt.image : pt.imageOverlay}
alt={pt.title}
/>
</div>
<div style={{ fontSize: "0.65rem" }}>{pt.title}</div>
</div>
</div>
)}
</Dropzone>
</div>
);
});
}
// Normally you would want to split things out into separate components.
// But in this example everything is just done in one place for simplicity
render() {
const { files } = this.state;
const self = this;
return (
<DragDropContext onDragEnd={this.onDragEnd}>
<Droppable droppableId="droppable">
{provided => (
<div
key="droppable"
{...provided.droppableProps}
ref={provided.innerRef}
>
<Dropzone
onDrop={files => self.addFilesToState(files)}
accept="image/jpeg, image/png"
>
{({ getRootProps, getInputProps }) => (
<section className="drag-drop-section">
<div {...getRootProps()}>
<input {...getInputProps()} />
<p className="drag-drop-text">
Drag 'n' drop some files here, or click to select files
</p>
</div>
</section>
)}
</Dropzone>
<div
style={{ display: "flex", flexDirection: "row", marginTop: 10 }}
>
<div style={{ display: "flex", flexDirection: "row" }}>
{self.renderPictureTypes()}
</div>
<div className="flex w-1/2 pl-2">
{self.renderPreviews(files)}
</div>
</div>
{provided.placeholder}
</div>
)}
</Droppable>
</DragDropContext>
);
}
}
// Put the thing into the DOM!
ReactDOM.render(<App />, document.getElementById("root"));
Here is the example code on codesandbox.
The photo's are successfully added to the right side where I render the thumbnails but I cant drag one of them then to the left side.
Any idea how to solve it?
<Draggable> should be inside <Droppable>
<Draggable /> components can be dragged around and dropped onto <Droppable />s. A <Draggable /> must always be contained within a <Droppable />. It is possible to reorder a <Draggable /> within its home <Droppable /> or move to another <Droppable />. It is possible because a <Droppable /> is free to control what it allows to be dropped on it.
see here

React. onClick event not firing

In my navbar, I have a button that will display a submenu (list of items) when clicked. Each item is their own child component and when clicked I want them to fire an event. The onClick event listener is not responding at all. However, other mouse events do apply (onMouseEnter, onMouseOut etc). Anyone might know what's up?
Child Component: NotificationItem.js
import React from "react"
import { connect } from "react-redux"
import { updateNotification } from "../../actions/notificationActions"
class NotificationItem extends React.Component{
constructor(props){
super(props)
this.handleOnClick = this.handleOnClick.bind(this)
}
handleOnClick = (event) => {
console.log("clicked")
// let notificationId = this.props.notification._id
// this.props.updateNotification(notificationId)
}
render(){
let {avatar, description, seen} = this.props.notification
return(
<div
onClick={this.handleOnClick}
className="d-flex notification-wrapper"
style={ seen ? (
{ width: "250px", whiteSpace: "normal", padding: "0.5rem" }
):( { width: "250px", whiteSpace: "normal", padding: "0.5rem", backgroundColor: "#d7e2f4" }
)
}
>
<div>
<img src={avatar} style={{ width: "25px"}} className="mr-2 rounded-circle"/>
</div>
<div>
{description}
</div>
</div>
)
}
}
Parent component: NotificationFeed.js
import React from "react"
import { connect } from "react-redux"
import NotificationItem from "./NotificationItem"
class NotificationFeed extends React.Component{
constructor(props){
super(props)
}
render(){
let notifications = this.props.notification.notifications
return(
<div className="dropdown-menu">
{notifications.map((notification, index) => {
return(
<div key={index}>
<NotificationItem notification={notification}/>
</div>
)
})}
</div>
)
}
}
const mapStateToProps = (state) => {
return{
notification: state.notification
}
}
export default connect(mapStateToProps)(NotificationFeed)
Edit: Something I noticed that might be of help. I'm using a bootstrap class to create this dropdown toggle-effect. When clicking on one of the items, the submenu closes immediately, without firing my desired event handler on the component.
<span className="dropdown" id="notifications-dropdown">
<Link to="#" className="nav-link text-light dropdown-toggle" data-toggle="dropdown">
<span
key={Math.random()}
>
<i className="fa fa-bell"></i>
</span> { windowWidth < 576 && "Notifications"}
<NotificationFeed/>
</Link>
</span>
For those still interested, this was a problem with Bootstrap. Because the elements were created inside a Bootstrap dropdown it had some logic I couldn't see. Whenever I would click on an element, the dropdown closes before the event-handler would even fire.
Opted, to create my own dropdown instead. Thanks all!
You created an arrow function, you do not need to bind it in the constructor
import React from "react"
import { connect } from "react-redux"
import { updateNotification } from "../../actions/notificationActions"
class NotificationItem extends React.Component{
state = {}
handleOnClick = (event) => {
console.log("clicked")
}
//or do not use arrow function then bind in the constructor
//constructor(props) {
//super(props);
//this.handleOnClick = this.handleOnClick.bind(this)
//}
// handleOnClick(event) {
// console.log("clicked")
// }
render(){
let {avatar, description, seen} = this.props.notification
return(
<div
onClick={this.handleOnClick}
className="d-flex notification-wrapper"
style={ seen ? (
{ width: "250px", whiteSpace: "normal", padding: "0.5rem" }
):( { width: "250px", whiteSpace: "normal", padding: "0.5rem", backgroundColor: "#d7e2f4" }
)
}
>
<div>
<img src={avatar} style={{ width: "25px"}} className="mr-2 rounded-circle"/>
</div>
<div>
{description}
</div>
</div>
)
}
try this
onClick={ (e) => this.handleOnClick(e)}
Try change your code, now it's like method:
handleOnClick(event){
console.log("clicked")
}

Categories

Resources