ReactJS redirection with id in link - reactjs

I am trying to redirect to another page from a button click. I have created my button on-click function as follows.
const buttonOnClick = (id) => {
this.props.history.push('/teams/team' + id);
}
The idea is that when I render the button, I add the buttonOnClick function with the id I want the link to have. Each button will have a different id based on how I'm creating it. This is my button code:
<button onClick={ buttonOnClick(id) }>Go</button>
However, this executes the function right as the button is rendered (without being clicked) because I'm using (), which is expected. How do I pass the id to the function without it executing the function on rendering?
Thanks.

Because you are calling that function instead of passing the function to onClick, change that line to this:
<button onClick={ () => buttonOnClick(id) }>Go</button>
=> called Arrow Function, which was introduced in ES6, and will be supported on React 0.13.3 or upper.

Related

I have an array of mp3 links for sounds. i am trying to use .map to show a button for each sound that plays the sound onClick

as the title says i am trying to use buttons to play the sounds from an array of animals.
<div>{dieren.map((dier:Dier) =>{
const audio = new Audio(dier.geluid)
return <div>
<div>{dier.dier}</div>
<button onClick={audio.play}>maak geluid</button>
</div>})}
</div>
But no sounds are playing at all
I am unsure what problem you are facing here, but one problem I see here for sure is that the handler for onClick will run no matter whether you click it or not. Instead of writing it like you have written it, you should try one of the following two methods:
Method 1: Arrow Functions
Replace the onClick of your Button with the following:
onClick={() => audio.play}
Method 2: Passing Function Reference
Inside your functional component, add the following code:
const playAudioOnClick = (audio) => {
audio.play;
}
Replace the onClick of your Button with the following:
onClick={(audio) => playAudioOnClick(audio)}

Prevent onClick event to happen in all rows instead of one sigle row per click

I have a table in which a I have a button that appears in every single row. This button displays an onClick event which adds two buttons elements below.
What happens : when I click on a button the onClick event is done in every single row instead of just the only one I clicked.
What I expect to happen: when clicking to the button in one row the event it's done on that single row.
Note : I am using material table and in one the of the columns I have a render method and the structure of the button is like the following:
<Button
disableRipple
className={(classes.buttonState, classes.textButtonStatePending)}
onMouseEnter={handleHover} //makes the buttons appear
onMouseLeave={handleHoverAway} //makes the buttons dissapear
onClick={handleHover}
onChange={handleHover}
>
Pending
</Button>
This is my event that makes hover over the button and it must show my components:
const handleHover = (): void => {
setShowButtonGroup(true);
};
So looking at the docs, it looks like a custom render method for a table column looks like this:
render: rowData => <YourCustomComponent />
In your case, you are rendering a <Button> with a bunch of handlers, including onClick. Assuming your rowData has some kind of unique value like id, you can use this to tie the button click to the row:
render: rowData => <Button onClick={() => handleClick(row.id)}>Pending</Button>
I've added a separate click handler for this, it's not necessary but it helps to keep things separate. So now you need a click handler that is 'row aware' - normally this might look something like this:
const handleClick = (id): void => {
setVisibleRowId(id)
};
Finally, you use this id wherever you are rendering the buttons that you want to show/hide, so if it's in another column render method:
render: rowData => rowData.id === visibleRowId ? <Button>My row was clicked</Button> : undefined
ETA: regarding your additional question
I don't know how to pass the key to the button either : onClick={ handleHover(time.teamMember[1])}
This will call your handleHover function on every render, which you don't want. You have wrap this call in a new function - i.e. pass a function that is invoked only on click:
onClick={() => handleHover(time.teamMember[1])}

React global click track handler

I am new to react and working on a legacy codebase. Am wondering if we can write a global button click handler for click tracking.
The jQuery equivalent of this would be something like,
utilities.js :
var subscribeForClickTracking = function() {
$( "button" ).click((event) => { console.log($(event.target).html()) })
$( "p" ).click((event) => { console.log($(event.target).html()) })
}
In all the html files, will add reference to utiliies.js and this snippet of code.
$(document).ready(function () {
subscribeForClickTracking();
});
I have surfed about this and reached similar so questions, like
Higher Order React Component for Click Tracking
and https://www.freecodecamp.org/news/how-to-track-user-interactions-in-your-react-app-b82f0bc4c7ff/
But these solutions involve modifying the button's implementation, which would lead to huge change. (For a html form with 50+ buttons).
Is there an alternate approach to achieve something similar to the above jQuery approach.
Thanks in advance.
No, you can not do that. The reason is that React prevents you from doing global things to avoid side effects.
I think the proper React way would be to create your own Button component.
First create a new component :
export default Button = (props) => <button ...props />
Then, you can import and use Button instead of button in any component.
Then in your Button component, you can override your onClick method like this :
<button
...props
onClick={() => {
// doWhatYouWantHere;
props.onClick()
/>
However, as React is JavaScript, you can still use vanilla JavaScript to attach an event to every button

Mimic React custom component

I have a custom Reactjs component to display Pagination with next/previous buttons at the bottom of a grid. Now, the business needs to display the same component on top of the grid as well. How to display the previous /next button events based on the input provided in prev/next buttons at the bottom of the grid?
I tried using javascript innerHTML to mimic the behaviour. It works only with the display. It does not attach the event listener of the buttons. I tried even with
document.querySelector.addEventListener('click', ()=>{console.log('test')})
It does not work. Is there a better way to do with react.
I am going to just add some more content to Shmili Breuer answer.
If i understood you correctly you have 2 navigations, one at the top one at the bottom. The way you connect them would be through a state of you component, or a parent component if you are using functional component to render pagination stuff. So if you change the state it will reflect on both of your navigations. Also you can use only one function here, by passing a parameter, im gonna copy a code from before mentioned answer.
// first create a function
nextFunction = (condition) => {
if(condition){
this.setState(prevState=>({
page: prevState.page-1
}))
} else {
this.setState(prevState=>({
page: prevState.page+1
}))
}
}
// then use it in your button
<button onClick={() => this.nextFunction(some condition)}>Next</button>
Just put that component on top and bottom
<Grid>
<Pagination />
{...someOtherComponents}
<Pagination />
</Grid>
it's ok in react. Optimization that you want to do is overhead.
In react you would add an onClick attribute to an element you want to handle a click on.
Something like this
// first create a function
nextFunction = () => {
do next functionality....
}
// then use it in your button
<button onClick={() => this.nextFunction()}>Next</button>
This way you can have both top and bottom pagination call the same function.
Hope this helps

How to use onClick event on Link: ReactJS?

In React router, I have to and onClick attributes as shown below
<li key={i}><Link to="/about" onClick={() => props.selectName(name)}>{name}</Link></li>
state = {
selectedName: ''
};
selectName = (name) => {
setTimeout(function(){this.setState({selectedName:name});}.bind(this),1000);
// this.setState({selectedName: name});
}
to attribute navigates to about Route
onClick assigns value to state variable selectedName which will be displayed when navigated to About page.
When I give timeout insided function called on click, its navigating to new page and after sometime state is getting updated resulting in displaying previous name until state is updated with new name.
Is there a way where it will navigate to the new route only after the code in onClick function gets executed.
You can get the entire code [here].(https://github.com/pushkalb123/basic-react-router/blob/master/src/App.js)
One possible way is, Instead of using Link, use history.push to change the route dynamically. To achieve that remove the Link component and define the onClick event on li. Now first perform all the task inside onClick function and at the end use history.push to change the route means to navigate on other page.
In your case change the router inside setState callback function to ensure that it will happen only after state change.
Write it like this:
<li key={i} onClick={() => props.selectName(name)}> {name} </li>
selectName = (name) => {
this.setState({ selectedName:name }, () => {
this.props.history.push('about');
});
}
Check this answers for:
When to use setState callback
How to navigate dynamically using react router dom
Alternatively, I would recommend using URL Params in order to capture the name of the person that the about page is about. Thus, instead of the url being /about and the name being behind the scenes, it would be /about/tom or /about/pushkal. The way that you do this is by defining params in the URL router as such in your index.js:
<Route path="/about/:name" component={AboutPage}>
Now, when you link to the about page, you would do it as such:
<Link to={"/about/" + name}>{name}</Link>
Now, in your AboutPage component, you can access the name param as a prop in this.props.params.name. You can look at more examples here.
This method is a bit different than your current approach but I suspect it will lead to easier design later on

Resources