Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React-Router Link, how to trigger a click event on a Link from another component

I'm trying to set up a series of React-Router to have navigation within a certain component. I have it set up so the link tags work correctly but I'm trying to style them to look like this:

enter image description here

The styling is set up like this:

  <div className="btn-group" data-toggle="buttons">
      <label className="btn btn-primary-outline active">
        <input type="radio" name="options" id="option1" autocomplete="off" checked />Payments
      </label>
      <label className="btn btn-primary-outline">
        <input type="radio" name="options" id="option2" autocomplete="off" /> Bills
      </label>
      <label className="btn btn-primary-outline">
        <input type="radio" name="options" id="option3" autocomplete="off" /> Charge
      </label>
    </div>

And the current series of Links looks like this (with no styling):

<ul>
  <Link to='/options/option1'>option1</Link>
  <Link to='/options/option2'>option2</Link>
  <Link to='/options/option3'>option3</Link>
</ul>

The HTML (top) is written in HTML, not JSX, but that's not the issue. I am trying to combine the Link Components into the HTML above so that the options will trigger the functionality of the link tags.

In the React documentation I found this:

For communication between two components that don't have a parent-child relationship, you can set up your own global event system. Subscribe to events in componentDidMount(), unsubscribe in componentWillUnmount(), and call setState() when you receive an event. Flux pattern is one of the possible ways to arrange this.

So this gave me the idea of putting the Link tags inside of their respective labels, giving them a style of {{display: 'none'}}, and having the clicks on the radio buttons trigger a click on the respective Link tag. That would ensure all the same functionality happens that we'd expect from the Link tag (pushing to browser history etc).

However, the following is not working:

<label className="btn btn-primary-outline active" onClick={() => document.getElementById('linkToOption1').click() }>
    <Link to='/options/option1' id="linkToOption1" style={{display: 'none'}}>Option1</Link>
        <input type="radio" name="options" id="option1" autoComplete="off" defaultChecked />Option1
    </label>

In the previous example you can see I created an onClick event handler that selects the id of the Link tag and triggers a click.

like image 323
jmancherje Avatar asked Apr 04 '16 04:04

jmancherje


People also ask

How do you pass Click event to another component in react?

You can't really pass a click event to another component. But all you need from the click event in this case is a DOM element to anchor the menu to ( event. currentTarget ). And you certainly can use a ref to get a different DOM element to use for anchorEl .

How do you add an onClick event to a link in react?

To set an onClick listener on a link in React:Set the onClick prop on the link. The function you pass to the prop will get called every time the link is clicked.

Can Link have an onClick?

This is a type of JavaScript link - the onclick attribute defines a JavaScript action when the 'onclick' event for the link is triggered (i.e. when a user clicks the link) - and there is a URL present itself in the onclick attribute.

How do I redirect onClick react router?

To redirect to another page on button click in React: Use the useNavigate() hook, e.g. const navigate = useNavigate(); . Call the navigate() function, passing it the path - navigate('/about') . The navigate() function lets us navigate programmatically.


1 Answers

I was able to solve my problem so I am posting what worked for me. Please answer or comment if there's changes or a better solution.

I wasn't able to trigger a click event on a Link, but I was able to simulate the aspects that I needed.

For this to work I needed the following:

  1. on a click event push to browserHistory to update the route
  2. link the 'active' css class to the current view/URL (I accomplished this through component state)
  3. update the state whenever the url is changed (modified state on window popstate event, and also update the currentView state on component will mount)

This results in the ability for the correct tab to be highlighted when a tab is clicked, when the url is manually changed to a certain route, and when the browsers back / forward buttons are used.

This is all the code in my navmenu file that creates a pretty cool navigation component and works with react-router and browserHistory.

import React, { Component, PropTypes } from 'react'
import { Link, browserHistory } from 'react-router'

class Navmenu extends Component {
  constructor(props) {
    super(props)
    this.state = { currentView: '' }
    this.getClasses.bind(this)
  }

  // in case of url being manually set, figure out correct tab to highlight
  // add event listener to update the state whenever the back/forward buttons are used.
  componentWillMount() {
    this.changeLocation()
    window.addEventListener('popstate', this.changeLocation.bind(this))
  }

  componentWillUnmount() {
    window.removeEventListener('popstate', this.changeLocation.bind(this))
  }

  // update state based on the URL
  changeLocation() {
    const path = window.location.pathname.split('/')
    const currentView = path[path.length - 1]
    this.setState({ currentView })
  }

  // update state and update react-router route
  navigateToRoute(route) {
    this.setState({ currentView: route })
    browserHistory.push(`/options/${route}`)
  }

  // give correct tab the 'active' bootstrap class
  getClasses(link) {
    let classes = 'btn btn-primary-outline flex-button'
    if (this.state.currentView === link) {
      classes += ' active'
    }
    return classes
  }

  render() {
    return (
      <div className="btn-group flex-navbar" data-toggle="buttons">
        <label className={this.getClasses('option1')} onClick={() => this.navigateToRoute('option1')}>
          <input type="radio" name="options" id="option1" autoComplete="off" defaultChecked />option1
        </label>
        <label className={this.getClasses('option2')} onClick={() => this.navigateToRoute('option2')}>
          <input type="radio" name="options" id="option2" autoComplete="off" /> option2
        </label>
        <label className={this.getClasses('option3')} onClick={() => this.navigateToRoute('option3')}>
          <input type="radio" name="options" id="option2" autoComplete="off" /> option3
        </label>
      </div>
    )
  }
}

export default Navmenu
like image 127
jmancherje Avatar answered Oct 26 '22 02:10

jmancherje