简体   繁体   中英

check function is called in child component

I am trying to make a custom dropdown but with custom children component. Within the children custom component, there's an onChange event.

The problem now is whenever I trigger the onChange which is for the checkbox, the dropdown is closed.

https://codesandbox.io/s/lr677jv7l7

Partial code

render() {

    const { className, onOpen, children } = this.props
    const { openItems, selectedItem } = this.state

    return (
      <div className={classnames('customDropdown', className)}>
        <div tabIndex="1"
          onBlur={() => { this.setState({ openItems: false }) }}
          onFocus={() => { this.setState({ openItems: true }); onOpen && onOpen() }}>
          <button className="btn">
            {selectedItem}
          </button>

          <div className={classnames('items', { 'show': openItems === true, 'hide': openItems === false })}>
            {children && children}
          </div>
        </div>
      </div>
    )
  }

You need to get rid of following line: onBlur={() => { this.setState({ openItems: false }) }} It basically says that when your div wrapping the button loses focus (eg when you click the checkbox) it should set the state.openItems variable to false and therefore it closes the dropdown.

Edit: Check out working example here: https://codesandbox.io/s/jnq2rqwr53 .

Basically use onClick instead of blur and then you add click event to your document, so anytime user clicks anywhere on the document it calls your hide method and closes the modal. This way the selected checkbox gets checked, but if you want to dropdown to stay open after the selection you'll need to somehow tell the hide function not to execute if user clicked on the checkbox. I did it using ids and simple condition guard at the beginning of the hide method.

Code looks like this:

Hello.js

import React, { Component } from 'react';
import classnames from 'classnames'

export default class CustomDropdown extends Component {


  constructor() {
    super()

    this.state = {
      openItems: false,
      selectedItem: 'Please select'
    }

    this.show = this.show.bind(this);
    this.hide = this.hide.bind(this);
  }

  show() {
    this.setState({openItems: true});
    document.addEventListener("click", this.hide);
  }

  hide(e) {
    if (e.target.id === "1" || e.target.id === "2") {
      return false;
    }

    this.setState({openItems: false});
    document.removeEventListener("click", this.hide);
  }

  render() {

    const { className, onOpen, children } = this.props
    const { openItems, selectedItem } = this.state

    return (
      <div className={classnames('customDropdown', className)}>
        <div tabIndex="1">
          <button className="btn" onClick={this.show}>
            {selectedItem}
          </button>

          <div className={classnames('items', { 'show': openItems === true, 'hide': openItems === false })}>
            {children && children}
          </div>
        </div>
      </div>
    )
  }
}

index.js

import React, { Component } from 'react';
import { render } from 'react-dom';
import Hello from './Hello';
import './styles.css';

const styles = {
  fontFamily: 'sans-serif',
  textAlign: 'center'
}; 

class App extends Component {
  constructor() {
    super()
  }

  changeCheckbox = () => {
    console.log('something')
  } 

  render(){
    return(
      <div style={ styles }>
        <Hello>
          <div>
            my checkbox 1
              <input type="checkbox" onChange={this.changeCheckbox} id="1" />
          </div>

          <div>
            my checkbox 2
              <input type="checkbox" onChange={this.changeCheckbox} id="2" />
          </div>
        </Hello>
      </div>
    )
  }
}

render(<App />, document.getElementById('root'));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM