Closed Rikusor closed 7 years ago
How do u use react-onclickoutside
? Do you wrap a DOM component?
Hi,
Below is my component.
import React from 'react';
import PropTypes from 'prop-types';
import pull from 'lodash/pull';
import onClickOutside from 'react-onclickoutside'
import cxs from '../_helpers/classnames';
import DropdownItem from './DropdownItem';
import * as s from './styles';
class Dropdown extends React.Component {
constructor(props) {
super(props);
const selected = props.items.filter(item => item.selected).map(item => item.value);
this.state = {
opened: false,
selected,
};
this.valueChange = this.valueChange.bind(this);
this.toggle = this.toggle.bind(this);
this.setWrapperRef = this.setWrapperRef.bind(this);
}
setWrapperRef(node) {
this.wrapperRef = node;
}
handleClickOutside() {
this.close();
}
valueChange(value) {
let updatedSelected;
if (this.props.multiselect) {
const selected = this.state.selected;
updatedSelected = selected.includes(value) ? pull(selected, value) : selected.concat(value);
} else {
updatedSelected = [value];
}
this.setState({
selected: updatedSelected,
});
this.props.onChange(updatedSelected);
}
close() {
this.setState({
opened: false,
});
}
toggle(e) {
e.preventDefault();
this.setState({
opened: !this.state.opened,
});
}
render() {
const {
closeAfterClick,
items,
multiselect,
onChange,
...props
} = this.props;
const {
opened,
selected,
} = this.state;
const classNames = cxs({
dropdown: true,
dropdownOpened: opened,
}, s);
const itemsClassNames = cxs({
dropdownItems: true,
}, s);
const heading = items.filter(item => selected.includes(item.value)).map(item => item.name);
const maxHeight = opened ? items.length * 64 : 0;
const multiplyBy = Math.floor(items.length / 4);
const duration = 150 + (50 * multiplyBy);
return (
<div className={classNames} {...props} ref={this.setWrapperRef}>
<a className={s.dropdownHeading} href="#" onClick={this.toggle}>
{ selected.length ? heading.join('; ') : 'Select option' }
</a>
<ul className={itemsClassNames} style={{ maxHeight: `${maxHeight}px`, transitionDuration: `${duration}ms` }}>
{ items.map((item, idx) => {
const delay = opened ? (duration / items.length) * idx : 0;
return (
<DropdownItem
key={item.value}
onChange={() => {
this.valueChange(item.value);
if (closeAfterClick) {
this.close();
}
}}
multiselect={multiselect}
selected={selected.includes(item.value)}
style={{ 'transitionDelay': `${delay}ms` }}
>
{item.name}
</DropdownItem>
);
})}
</ul>
</div>
);
}
}
Dropdown.propTypes = {
closeAfterClick: PropTypes.bool,
items: PropTypes.arrayOf(PropTypes.object).isRequired,
multiselect: PropTypes.bool,
/**
* The change handler that will receive the updated values as it's only param
*/
onChange: PropTypes.func.isRequired,
};
Dropdown.defaultProps = {
closeAfterClick: true,
items: [],
};
export default onClickOutside(Dropdown);
Best regards, Riku
The problem is here - <div className={classNames} {...props} ref={this.setWrapperRef}>
You shouldn't passthrough all props, because react-onclickoutside
provide (inject into your component, so they can be used) props for you.
You should filter them out here:
const {
closeAfterClick,
items,
multiselect,
onChange,
...props
} = this.props;
Hi,
I get following warning using this library;
This repeats for following attributes;
Is there something to fix this Warning?