2016-07-28 2 views
1

私はReactを使用してオートコンプリート機能を作成しています。ユーザがリスト上の項目を選択すると、入力を更新します。私の問題は、入力がフォーカスを失ったときです。ユーザーがメニュー内でメニューを選択しない限り、メニューが消えてしまいます。現在、メニューの表示はshowDropDownというプロパティに基づいています。レンダリングメソッドでは、showDropDownならメニューコンポーネントを構築します。レンダーメソッドは、メニュー項目のクリックリスナーの前に呼び出され、onClickが呼び出される前にそれらを削除しているようです。入力がフォーカスを失ったが、フォーカスがメニューReactでのフォーカスの管理

+0

どこ 'showDropDown'状態に依存するコードはありますか? –

+0

コピー上にどのようにそれが見逃されたか分かりません。再び追加されました – user1760412

答えて

0

していない私は、これは何が必要ないと思えば、私がする必要がどのような

handleOnBlur =() => { 
    this.setState({ showDropDown: false }); 
}; 

handleOnFocus =() => { 
    this.setState({ showDropDown: true }); 
}; 
handleRenderSubComponents = (options) => { 
    ... 
    return options.map((option) => { 
    ... 
    return (<li key={displayString} className={className}> 
     <span onClick={() => {this.handleOnItemSelect(option, fieldInput);}} style={{ cursor: 'pointer' }}> 
     {displayString} 
     </span> 
    </li>); 
    }); 
}; 
render() { 
... 
    return (
    <div className={className}> 
     <div> 
     <input 
      style={{ position: 'relative' }} 
      disabled={disabled} 
      ref={(inputElem) => {this.inputElem = inputElem;}} 
      valueLink={{ value: this.state.value, requestChange: (value) => this.handleOnChange(value) }} 
      onBlur={this.handleOnBlur} 
      onFocus={this.handleOnFocus} 
      onKeyUp={this.handleOnKeyUp} 
     /> 
     </div> 
     <ul className="dropdown-menu dropdown-menu-justify" style={dropDownStyle} > 
     {showDropDown && this.handleRenderSubComponents(options)} 
     </ul> 
    </div> 
); 
} 

は非表示のメニューです。キーは、コンテナのonMouseDownイベントが入力のonBlurより前に発生することです。そこで、onBlurでチェックできるクラス変数を設定し、コンテナがクリックされた場合は、入力にフォーカスを戻します。 setTimeoutはこの変数をもう一度クリアするので、実行順序はonMouseDown、onBlur、setTimeoutコールバックになります。

jsfiddle

class App extends React.Component { 
    constructor(props) { 
    super(props); 
    this.onInputChange = this.onInputChange.bind(this); 
    this.onInputBlur = this.onInputBlur.bind(this); 
    this.onContainerMouseDown = this.onContainerMouseDown.bind(this); 
    this.onOptionClick = this.onOptionClick.bind(this); 

    this.state = { 
     input: '', 
     showList: false 
    }; 

    this.options = ['Option 1', 'Option 2', 'Option 3', 'Option 4']; 
    } 
    componentWillUnmount() { 
    clearTimeout(this.containerMouseDownTimeout); 
    } 
    onInputChange(e) { 
    this.setState({input: e.target.value, showList: e.target.value.length > 2}); 
    } 
    onInputBlur() { 
    const showList = this.clickedInContainer && this.state.input.length > 2; 

    this.setState({ 
     showList 
    }); 

    if (showList) { 
     this.input.getDOMNode().focus(); 
    } 
    } 
    onContainerMouseDown() { 
    this.clickedInContainer = true; 

    this.containerMouseDownTimeout = setTimeout(() => { 
     this.clickedInContainer = false; 
    }); 
    } 
    onOptionClick(option) { 
    this.setState({ 
     input: option, 
     showList: false 
    }) 
    } 
    renderList() { 
    return (
     <ol style={{cursor: 'pointer'}}> 
       {this.options.map((o, i) => <li key={i} onClick={() => this.onOptionClick(o)}>{o}</li>)} 
     </ol>); 
    } 
    render() { 
    return (
     <div onMouseDown={this.onContainerMouseDown}> 
      <input ref={ref => this.input = ref} value={this.state.input} 
      onChange={this.onInputChange} onBlur={this.onInputBlur}/> 
      {this.state.showList && this.renderList()} 
     </div> 
    ) 
    } 
} 

React.render(<App />, document.getElementById('container')); 
関連する問題