2017-11-09 3 views
1

Ich habe eine Menü-Box in meiner Reaktion App und ich zeige, wenn ich auf Menü-Taste anzeigen und ausblenden, wenn Menü geöffnet ist. Ich möchte Menü auszublenden, wenn ich außerhalb des Menüs klickenEvent.Target nimmt reagieren Kind Komponenten separat

class MenuButton extends Component { 
constructor (props) { 
    super (props) 
    this.state = {showMenu: false} 
    this.toggleMenu = this.toggleMenu.bind(this) 
} 

toggleMenu() { 
    let showMenu = !this.state.showMenu 
    this.setState({showMenu}) 
} 

componentDidMount() { 
    window.addEventListner('click', e => { 
    if (e.target !== document.getElementById('menu-div') { 
    this.setState({showMenu: false}) 
    } 
    }) 
} 

render() {} { 
    return (
    <div> 
    <button onClick={this.toggleMenu}>Menu</button> 
    {this.state.showMenu ? <div id='menu-div><Menu /></div> : null} 
    </div> 
) 
} 
} 

und mein Menü Component viele Kind-Komponenten

const Menu =() => { 
    return (
    <div> 
     <Component1/> 
     <Component2/> 
     <Component3/> 
    </div> 
) 
} 

aber einen Klick auf diesen untergeordneten Komponenten schließen mein Menü als event.target hat schenkt anderen Knoten

Antwort

3

würde ich nicht getElementById verwenden noch suchen Elemente in der DOM. Dies ist nicht der "Reaktionsweg", Dinge zu tun, und es wird als schlechte Praxis angesehen.
Verwenden Sie stattdessen die refs API that react provides und greifen Sie einen Verweis auf den Knoten.
Sie können Ereignis-Listener von mousedown hinzufügen und überprüfen, ob die ref das Ziel enthält, wenn nicht, bedeutet dies, dass Sie außerhalb der ref (das Menü in Ihrem Fall) sind. Es bleibt also nur noch, den Zustand zu setzen, um ihn zu schließen.

Hier ist ein Lauf Schnipsel des Codes mit der Umsetzung i erwähnt:

class MenuButton extends React.Component { 
 
    constructor(props) { 
 
    super(props); 
 
    this.state = { showMenu: false }; 
 
    } 
 

 
    componentDidMount() { 
 
    document.addEventListener("mousedown", this.handleOutsideClick); 
 
    } 
 

 
    componentWillUnmount() { 
 
    document.removeEventListener("mousedown", this.handleOutsideClick); 
 
    } 
 

 
    toggleMenu =() => { 
 
    let showMenu = !this.state.showMenu; 
 
    this.setState({ showMenu }); 
 
    }; 
 

 
    handleOutsideClick = event => { 
 
    if (this.menuRef && !this.menuRef.contains(event.target)) { 
 
     this.setState({ showMenu: false }); 
 
    } 
 
    }; 
 

 
    setRef = ref => { 
 
    this.menuRef = ref; 
 
    }; 
 

 
    render() { 
 
    const { showMenu } = this.state; 
 
    return (
 
     <div> 
 
     <button onClick={this.toggleMenu}>Menu</button> 
 
     {<Menu className={`${!showMenu && "hide"}`} setRef={this.setRef} />} 
 
     </div> 
 
    ); 
 
    } 
 
} 
 

 
class Menu extends React.Component { 
 
    render() { 
 
    const { setRef, className } = this.props; 
 
    return (
 
     <div className={`menu ${className}`} ref={setRef}> 
 
     <div>comp 1</div> 
 
     <div>comp 2</div> 
 
     <div>comp 3</div> 
 
     </div> 
 
    ); 
 
    } 
 
} 
 

 
ReactDOM.render(<MenuButton />, document.getElementById("root"));
.hide{ 
 
    display: none; 
 
} 
 

 
.menu{ 
 
    border: 1px solid #333; 
 
    padding: 5px; 
 
    max-width: 60px; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> 
 
<div id="root"></div>

+0

das ist nett, ich werde meinen Code zu diesem –

+2

aktualisieren @RishabhMishra Bitte akzeptieren Sie diese Antwort anstelle von mir. –

1

Sie sollten nicht direkt auf DOM abfragen. Verwenden Sie stattdessen reagieren die refs und verwenden Sie dann contains Eigenschaft des Elements

componentDidMount() { 
    window.addEventListner('click', e => { 
    if (e.target !== this.refOfMenu && !this.refOfMenu.contains(e.target)) { 
    this.setState({showMenu: false}) 
    } 
    }) 
} 
+3

obwohl dies wahr ist (mit 'contains') ist dieser Ansatz sehr schlechte Praxis, die zur Abfrage 'DOM' bei jedem Klick (und sogar zweimal) –

Verwandte Themen