How to differentiate on click handler?

Viewed 64

I have a navigation class component in which I want to use modal after clicking in 'about' or 'contact'. I use event handler which changes state and then open modal, but I don't know how to differentiate the click between 'about' and 'contact' to open different modal. Any help?

class Navbar extends Component {
    state = {
        clicked: false
    }

    clickHandler = (event) => {
        event.preventDefault();
        //console.log('clicked!');
        this.setState({clicked: true});   
    }

    render () {
        const aboutClick = (<a href='/' onClick={this.clickHandler}>About</a>);
        const contactClick = (<a href='/' onClick={this.clickHandler}>Contact</a>);
        
        const modalAbout = (<Modal show={this.state.clicked}><About /></Modal>);
        const modalContact = (<Modal show={this.state.clicked}><Contact /></Modal>);

        const modal = aboutClick ? modalAbout : modalContact;

        return (
            <div>
                {modal}      
                <ul className='Navbar'>
                    <li>{aboutClick}</li>
                    <li>{contactClick}</li>
                    <li><NavLink to={'/admin'}>Admin</NavLink></li>
                </ul>
            </div>
        );
    }        
}   
export default Navbar;
3 Answers

You can curry a disambiguating value.

clickHandler = (value) => (event) => {
  event.preventDefault();

  if (value === 'about') {
    // do about stuff
  }
  if (value === 'contact') {
    // do contact stuff
  }       

  this.setState({clicked: true});   
}

...

const aboutClick = (<a href='/' onClick={this.clickHandler('about')}>About</a>);
const contactClick = (<a href='/' onClick={this.clickHandler('contact')}>Contact</a>);

There are several ways of doing this, most obvious is to extend clichandler with additional parameter and adapt the code like this:

class Navbar extends Component {
    state = {
        clicked: false,
        type: null,
    }

    clickHandler = (event, type) => {
        event.preventDefault();
        //console.log('clicked!');
        this.setState({clicked: true, type});
    }

    render () {
        const aboutClick = (<a href='/' onClick={(event) => this.clickHandler(event, 'about')}>About</a>);
        const contactClick = (<a href='/' onClick={(event) => this.clickHandler(event, 'contact')}>Contact</a>);
        
        const modalAbout = (<Modal show={this.state.clicked}><About /></Modal>);
        const modalContact = (<Modal show={this.state.clicked}><Contact /></Modal>);

        const modal = aboutClick ? modalAbout : modalContact;

        return (
            <div>
                {modal}      
                <ul className='Navbar'>
                    <li>{aboutClick}</li>
                    <li>{contactClick}</li>
                    <li><NavLink to={'/admin'}>Admin</NavLink></li>
                </ul>
            </div>
        );
    }        
}   
export default Navbar;

Another is to add data property that can be used to determine which link was clicked:

class Navbar extends Component {
    state = {
        clicked: false,
        type: null,
    }

    clickHandler = (event) => {
        event.preventDefault();
        // Read the type of modal from data-modal
        this.setState({clicked: true, type: event.currentTarged.dataset.modal});
    }

    render () {
        const aboutClick = (<a href='/' onClick={this.clickHandler} data-modal="about">About</a>);
        const contactClick = (<a href='/' onClick={this.clickHandler} data-modal="contact">Contact</a>);
        
        const modalAbout = (<Modal show={this.state.clicked}><About /></Modal>);
        const modalContact = (<Modal show={this.state.clicked}><Contact /></Modal>);

        const modal = aboutClick ? modalAbout : modalContact;

        return (
            <div>
                {modal}      
                <ul className='Navbar'>
                    <li>{aboutClick}</li>
                    <li>{contactClick}</li>
                    <li><NavLink to={'/admin'}>Admin</NavLink></li>
                </ul>
            </div>
        );
    }        
}   
export default Navbar;

You can try doing it like the following code snippet:

const {useState} = React;

function App() {
  const [modal, setModal] = useState(<div></div>);
  const handleClick = (e) => {
    if (e.target.id === "about") {
      setModal(<div>About Modal</div>)
    }
    if(e.target.id === "contact") {
      setModal(<div>Contact Modal</div>)
    }
  }
  return (
    <div className="App">
      <button id="about" onClick={handleClick}>About</button>
      <button id="contact" onClick={handleClick}>Contact</button>
      {modal}
    </div>
  );
}

ReactDOM.render(
  <App />,
  document.getElementById("react")
);
<div id="react"></div>
<script src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>

Related