我有两个下拉列表作为道具传递给组件。我可以用单独的状态控制两者,但我认为这可以用一个状态来完成吗?
标题
<iframe width="560" height="315" src="https://www.youtube.com/embed/Gl7ABg9lnBM" frameborder="0" allowfullscreen></iframe>
HeaderDropdown
导入来自&#39;反应&#39 ;;
的反应import React from 'react';
import DarkLabel from './DarkLabel';
import HeaderDropdown from './HeaderDropdown';
export default class Header extends React.Component {
componentWillMount() {
this.setState({
listOpen: false
})
}
render() {
...
return (
<div className="row header">
<div className="col-xs-10">
<DarkLabel classExtra="dark-label-lg" icon="/images/system-icons/document_empty.png"
content={taskCode}/>
<DarkLabel classExtra="dark-label-2x dark-label-lg" icon="/images/system-icons/building.png"
dropdown=<HeaderDropdown data={this.props.enquiry.entity ? this.props.enquiry.entity : null}/>
content={this.props.enquiry.entity ? this.props.enquiry.entity.name : 'ERROR'}
right_icon="/images/system-icons/bullet_arrow_down.png"/>
<DarkLabel classExtra="dark-label-md" icon="/images/system-icons/ceo.png"
dropdown=<HeaderDropdown data={this.props.enquiry.contact ? this.props.enquiry.contact : null}/>
content={this.props.enquiry.contact ? this.props.enquiry.contact.firstName + ' ' + this.props.enquiry.contact.lastName : '-'}
right_icon="/images/system-icons/bullet_arrow_down.png"/>
<DarkLabel classExtra="flag"
content={'/images/flags/large/'+this.props.enquiry.entity.country.countryCode+'.png'}
right_icon="/images/system-icons/cog.png" right_icon_callback={this.handleAddressModal.bind(this)}/>
</div>
</div>
)
}
}
我怎样才能这样做,这样一个人可以一次只打开一个,如果点击另一个人则关闭所有其他人?我是否需要存储来自这个&#39;当我将click事件绑定到HeaderDropdown?
我错过了一些问题。当用户点击DarkLabel中的right_icon时,就会发生这种情况。
DarkLabel
export default class HeaderDropdown extends React.Component {
componentWillMount() {
}
render() {
return (
<div>
<div className="dark-label-dropdown">
Test
</div>
</div>
);
}
}
答案 0 :(得分:1)
您可以做的是向onClick
添加HeaderDropdown
方法,并在Header
处理状态。正确的方法是使用某种商店(redux),但这可能超出了这个例子的范围。
所以简而言之,我建议你改变你的标题:
import React from 'react';
import DarkLabel from './DarkLabel';
import HeaderDropdown from './HeaderDropdown';
export default class Header extends React.Component {
componentWillMount() {
this.setState({
listOpen: false,
activeDropdown: 1
})
}
render() {
const headerDropdownA = (
<HeaderDropdown
data={...}
onClick={() => this.setState({activeDropDown: 1})}
isActive={this.state.activeDropdown === 1}
/>
)
const headerDropdownA = (
<HeaderDropdown
data={...}
onClick={() => this.setState({activeDropDown: 2})}
isActive={this.state.activeDropdown === 2}
/>
)
return (
<div className="row header">
<div className="col-xs-10">
<DarkLabel classExtra="..."
dropdown={headerDropdownA}
content={...}
right_icon="/images/system-icons/bullet_arrow_down.png"/>
<DarkLabel classExtra="..."
dropdown={headerDropdownB}
content={...}
right_icon="/images/system-icons/bullet_arrow_down.png"/>
</div>
</div>
)
}
}
我添加了当前活动下拉列表的状态。在您的下拉列表中,您可以使用this.props.isActive
访问活动状态。
但可能这还不够,因为每次点击都会再次切换下拉列表,当您点击选项时也是如此?但它可能会给你一个很好的起点。
答案 1 :(得分:0)
您可以创建一个高阶组件来检测组件外部的点击,例如
import React, { Component, PropTypes } from 'react';
import ReactDOM from 'react-dom';
const clickOutsideEvents = [ 'mousedown', 'touchstart' ];
const isDescendant = ( el, target ) => target !== null ? el === target || isDescendant( el, target.parentNode ) : false;
export default class ClickOutside extends Component {
static propTypes =
{
children : PropTypes.node,
onClickOutside : PropTypes.any,
};
componentDidMount()
{
if ( !this.props.onClickOutside ) return;
clickOutsideEvents.forEach( e => document.addEventListener( e, this.handleClickOutside ) )
}
/**
* Remove the listener in case the props change and there is not ClickAway handler
* @param { Object } prevProps
*/
componentDidUpdate( prevProps )
{
if ( prevProps.onClickOutside !== this.props.onClickOutside )
{
clickOutsideEvents.forEach( e => document.removeEventListener( e, this.handleClickOutside ) );
if ( this.props.onClickOutside )
{
clickOutsideEvents.forEach( e => document.addEventListener( e, this.handleClickOutside ) )
}
}
}
/**
* Remove listeners when Component unmount
*/
componentWillUnmount()
{
clickOutsideEvents.forEach( e => document.removeEventListener( e, this.handleClickOutside ) );
}
/**
* Call callback on ClickAway and pass the event
* @param event
*/
handleClickOutside = ( e ) =>
{
const el = ReactDOM.findDOMNode( this );
if ( document.documentElement.contains( e.target ) && !isDescendant( el, e.target ) )
{
this.props.onClickOutside( e );
}
};
/**
* Render the Elements that are Wrapped by the ClickAway
*/
render()
{
return this.props.children;
}
}
然后使用此HOC包装您的下拉菜单,并根据
设置组件的状态e.g。
setDropdownState(){
this.setState({ listOpen: false });
}
render(){
return(<ClickOutside onClickOutside={ this.setDropdownState.bind( this ) }>
<HeaderDropdown listOpen={ this.state.listOpen }>
</ClickOutside>)
}
您可以查看此实施https://github.com/AvraamMavridis/react-clickoutside-component