6

I want to create a React component with a render method that has an <a> tag that wraps an entire "box", if you will, which redirects to another page when clicked. Within said box there is a <button> that can be clicked that activates an event that changes state. What I want to be able to do is click the <button> and trigger the event without the redirect from the <a> tag occurring.

Tried some ideas with stopPropagation() but no luck :/ I don't want to move the button outside of the <a> tag either so not sure where to go from here.

It seems like it should be something simple but I just can't figure it out. Thanks!

the render method looks like this:

render(){
 return(
  <div>
   <a href="http://www.google.com"> 
    <div className="box">

     <h2 className="title">Random Title</h2>

     <button onClick={this.handleClick}> Like </button>

    </div>  
   </a>
  </div> 
 )
}

handleClick() would look something like this:

handleClick = () => {
  if (this.state.liked) {
  console.log("disliking")
} else {
  console.log("liking")
}

this.setState({ liked: !this.state.liked})
}
JAbrams
  • 325
  • 4
  • 7
  • 18

3 Answers3

2

you can achieve this with a simple trick. see what I did -

  1. replace the anchor with a div and place a click handler
  2. add a flag (clicked) with in the component and ignore in div click handler if it's a button click
  3. reset the flag

update - check out this js fiddle : https://jsfiddle.net/rabinarayanb/pvx2n3x3/

note - I have used es5 syntax. you can convert to es6

(function() {   
    var BoxSetup = React.createClass({


        clicked : "",

        getInitialState : function () {
            return { clickCount : 0};
        },

        handleDivClick : function (event) {
            if (this.clicked !== "Button") {
                window.location.href = "http://www.google.com";
            }

            // reset
            this.clicked = "";
        },

        handleButtonClick : function (event) {
           this.clicked = "Button"
           this.setState({
                clickCount : ++this.state.clickCount
           });
        },

        render : function () {

            return (
            <div>
                <div onClick={this.handleDivClick} style={ { }}>
                    <div style={ { width : "100px", height : "100px", border : "1px solid red" } }>
                        <h2 className="title">{ this.state.clickCount }</h2>
                        <button onClick={this.handleButtonClick}> Like </button>
                    </div>
                </div>
            </div> 
            );
        }
    });

    var element = React.createElement(BoxSetup, { title : "Hello" });

    ReactDOM.render(element, document.getElementById("app"));    
})();
Rabi
  • 2,210
  • 17
  • 18
  • thanks for the suggestion, will try it shortly. what is the point of the (event) parameter that you are giving to handleDivClick and handleButtonClick? – JAbrams Jan 16 '17 at 07:11
  • In this case, passing the parameter is not required. But, yes, if you want to do some operations like 'event.preventDefault();' you need to pass the params. – Rabi Jan 16 '17 at 07:54
1

What you are wanting to do does not seem possible. Once the user clicks on the <a> enclosed content they will be redirected to the linked content, in your case: http://www.google.com If you want to execute your function then follow the link you must remove the <a> tag and put window.location = "http://www.google.com"; at the end of your function.

Sienile
  • 186
  • 9
1

One way this can be done is by setting a reference to the anchor element, then using the button elements onMouseEnter and onMouseLeave to programatically change the anchor elements href property whenever the user moves the mouse over the Like button.

class Test extends React.Component {

  constructor(props){
    super(props)
    this.state={ likes:0 }
    this.anchorElement=null;
  }

  enter = () => { this.anchorElement.href='javascript:;'; }
  leave = () => { this.anchorElement.href='http://www.google.com'; }
  handleClick = () => { this.setState({ likes: ++this.state.likes}); }

  render() {
    return (
      <div>
        <div>{'Likes:'+this.state.likes}</div>
        <a href="http://www.google.com" ref={(el) => { if (el) { this.anchorElement = el; } }}>
          <div>
            <h2 className="title">Random Title</h2>
            <button onClick={this.handleClick} onMouseEnter={this.enter} onMouseLeave={this.leave}> Like </button>
          </div>
        </a>
      </div>
    );
  }
}

See it in action: Working fiddle

In the fiddle you will note the link is activating, but is not going anywhere because it is effectively "turned off" while the button is under the mouse. If you want to get rid of the appearance of activation on the link, a little more manipulation of the anchor element is needed, or simply set the a:active css property to the same color as the base/active color.

Personally, I would avoid the scenario if possible, but that's just good advice, something that more folks around here should learn is not the same thing as an answer.

hawkeyegold
  • 129
  • 5