2016-05-20 6 views
0

コンポーネントに小道具として2つのドロップダウンが渡されています。私は別の状態で両方を制御することができますが、これはすべて1つの状態で行うことができると思いますか?ReactJSの複数のドロップダウン、一度に1つしか開いていない

ヘッダ

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> 
     ) 
    } 

} 

HeaderDropdown

インポート 'が反応する' と反応させ;

export default class HeaderDropdown extends React.Component { 

    componentWillMount() { 

    } 

    render() { 

     return (
      <div> 
       <div className="dark-label-dropdown"> 
        Test 
       </div> 
      </div> 
     ); 
    } 
} 

別のものをクリックすると、一度に1つだけ開くことができ、他のものを閉じることができますか? ClickイベントをHeaderDropdownにバインドするときに「this」から何かを保存する必要がありますか?


私は質問から何かを逃しました。これは、ユーザーがDarkLabelのright_iconをクリックしたときに発生する必要があります。

DarkLabel

import React from 'react'; 

export default class DarkLabel extends React.Component { 

    componentWillMount() { 

    } 

    truncate(limit) { 
... 
    } 

    render() { 
     var icon = '', content = ''; 
     var rightIcon = ''; 
     ... 

     return (
      <div className={'pull-left dark-label-wrapper '+this.props.classExtra}> 
       {icon} 
       <div>{content}</div> 
       {rightIcon} 
       {this.props.dropdown} 
      </div> 
     ); 
    } 
} 
+0

を確認することができます。このようにコンストラクタであなたの状態を初期化する必要があります 'this.state = {listOpen:偽}' –

+0

componentWillMountとの違いは何ですか? – imperium2335

+1

は実際に、機能的にそれほど違いが知る限り存在しませんが、コンストラクタは、クラスのプロパティを初期化する方法はるかに慣用的です。 –

答えて

1

あなたは何ができるか、あなたのHeaderDropdownonClickメソッドを追加し、Headerそのために状態を処理です。適切な方法は、ある種のストア(redux)を使用することですが、これはこの例の範囲外になる可能性があります。

だから、要するに、私はあなたがこのToヘッダーに変更を提案:

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でアクティブ状態にアクセスできます。

しかし、すべてのクリックが再びドロップダウンを切り替えることができますので、あなたはオプションをクリックするとpropablyこれはすでにも、十分ではないのだろうか?しかしそれはあなたに良い出発点を与えるかもしれません。

+0

おかげで、私は私がところでFluxibleストアを使用しています、それをしようとします(コンポーネントは反応することが) – imperium2335

+0

私の編集をご覧ください。 – imperium2335

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を使用してドロップダウンをラップし、その

例えばに基づいて、コンポーネントの状態を設定

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

関連する問題