Surya
Surya

Reputation: 71

React onClick event not firing when it is conditionally rendered

I am building a searchDropdown component in React. I want to render dropdown only when search field is active. So I put a condition to render dropdown.

But when the dropdown is rendered conditionally, onClick events inside dropdown are not triggering.

My component is below.

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {List, ListItem} from 'material-ui/List';
import {Card} from 'material-ui/Card';
import Divider from 'material-ui/Divider';
import TextField from 'material-ui/TextField';
import resources from '../../resources/resources';
import cx from 'classnames';

import './SearchDropdown.scss';

class SearchDropdown extends Component {
  constructor(props) {
    super(props);
    this.cardContainerStyle = {
      'maxHeight': '300px',
      'overflow': 'scroll',
      'border': '1px solid rgb(158, 158,158)'
    };
    this.searchFieldUnderlineStyle = {
      'borderBottom': '1px solid #ccc'
    }
    this.state = {
      dropdownStyle: {}
    };
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.isActive && this.props.isActive !== nextProps.isActive) {
      this.shouldSetBounds = true;
    } else {
      this.shouldSetBounds = false;
    }
  }



  componentDidUpdate() {
    if(this.shouldSetBounds) {
      this._setDropdownBounds();
      this.shouldSetBounds = false;
    }
  }

  componentDidMount() {
    window.addEventListener('scroll',  this._handleScroll);
  }

  componentWillUnmount() {
    window.removeEventListener('scroll',  this._handleScroll);
  }

  _handleScroll = () => {
    if (this.props.isActive) {
      this._setDropdownBounds();
    }
  }

  _setDropdownBounds() {
    const dropdownContainerOffset = this.dropdownContainer.getBoundingClientRect();
    const containerTop = dropdownContainerOffset.top;
    const containerLeft = dropdownContainerOffset.left;
    const viewportHeight = window.innerHeight;
    const viewportWidth = window.innerWidth;
    const dropdownStyle = {
      top: dropdownContainerOffset.top + dropdownContainerOffset.height,
      left: dropdownContainerOffset.left
    };

    if (containerTop > viewportHeight/2) {
      dropdownStyle.top = 'auto';
      dropdownStyle.bottom = viewportHeight - containerTop;
    }
    this.setState({ dropdownStyle });
  }

  _renderDropdown() {
    const {onSelect, datalist = []} = this.props;

      return (
        <div className="search-dropdown-wrapper" style={this.state.dropdownStyle} onClick={(event) => {alert("Outer wrapper")}}>
          <Card containerStyle={this.cardContainerStyle}>
            <div>
            {"Sample Dropdown"}
            </div>
          </Card>
        </div>
      );
  }

  _renderSearchField() {
    const {value, handleSearch} =  this.props;

    return (
      <TextField
        value={value}
        onChange={handleSearch}
        fullWidth={true}
        hintText={resources.BRAND_SEARCH}
        underlineStyle={this.searchFieldUnderlineStyle}
      />
    );
  }

  render() {
    const {isActive, onBlur} = this.props;

    return (
      <div className="search-dropdown-container field-wrapper"
        ref={dropdownContainer => this.dropdownContainer = dropdownContainer}
        onBlur={onBlur}
        >
        {this._renderSearchField()}
        {isActive && this._renderDropdown()}
      </div>
    );
  }
}

SearchDropdown.propTypes = {
  isActive: React.PropTypes.bool.isRequired,
  value: React.PropTypes.string,
  datalist: React.PropTypes.array,
  handleSearch: React.PropTypes.func.isRequired,
  onSelect: React.PropTypes.func
}

export default SearchDropdown;

In above code, _renderDropdown will only execute when isActive is true. The compoenent is getting rendered perfectly with all styles when the search field is active. But when this component is rendered, the onClick event on the div with class search-dropdown-wrapper is not working.

I'm not sure where I'm doing mistake. Please let me know if there is any proper way to do this. Thanks.

Upvotes: 3

Views: 1705

Answers (2)

Surya
Surya

Reputation: 71

I finally made it work.

There is nothing wrong with the arrow function _renderDropdown used. The problem is with the onBlur event attached to the parent div with class search-dropdown-container of _renderDropdown. I have removed that onBlur event from there and added to search-dropdown-wrapper div. Then it started working fine.

What I think is, The search-dropdown-wrapper position is fixed and so it will not be as part of search-dropdown-container technically. So click event happening on the search-dropdown-wrapper triggers onBlur event of search-dropdown-container first. So, the click event is not firing on search-dropdown-wrapper

Upvotes: 4

Lingaraju E V
Lingaraju E V

Reputation: 503

Please bind this to all methods in your class in the constructor like for example -

constructor(props) { this._handleScroll = this._handleScroll.bind(this) this._setDropdownBounds = this._setDropdownBounds.bind(this) }

FYI

Upvotes: 0

Related Questions