Capturing onClick in a React Router Link - reactjs

Customary "I am new to React, Redux, and ES6"...
I need to notify my Component, or more specifically call a Action (or similar, I need to update an object in the store) whenever a user clicks on a redux-router Link. For example:
render(){
return (
<Link to={'/leaf/' + node.Id}>
<div className="col-md-2" style={divStyle}>
<label>
{node.Title}
</label>
</div>
</Link>
);
}
I want to be notified when the user clicks the Link. I don't want to stop anything from happening, I just want to fire off an async call back to the store so a variable gets updated.
How would I do this?

You can probably attach an onClick={// some function} prop to the Link element. If that doesn't work, you can add it to the label html element.
It shouldn't stop anything from propagating unless you specifically tell it to.

Related

Make child element of Link not route

I'm coding an application where people can make posts, and comment on them.
All of the posts are displayed on one page.
If a post is clicked the user gets routed to that post's page, which contains the full post, more details, and all of that post's comments.
Currently, I have the post div wrapped in a react-router Link. That works swell, except that when I click a button inside that div, I still get routed.
I want everywhere in the div to be "clickable", except actions like other Links or buttons.
<Link to={`/${_id}`}>
<div>
<button>I don't want this button to route</button>
</div>
</Link>
I'm not sure if there is a way to do this, but I can't find anything on it. I found one guy on another forum asking the same thing, but it was old and never got answered. Maybe I'm missing it, but I can't find it in the react-router docs. Maybe react-router is not even capable of this, idk?
Something like a quickfix but I don't know if its the best way to address this. I am looking first at the useRef but no avail.
Using something like e.preventDefault on the onClicks will probably save a lot of headache
<Link to="/">
<h1>Home</h1>
<button onClick={(e) => e.preventDefault()}>HAIYAAA</button>
</Link>
On hindsight this seems to be a Event Bubbling Issue right there.
See a fiddle here: https://codesandbox.io/s/react-router-forked-5rj2b?file=/index.js
EDIT:
Probably a much more dynamic way is to add a condition at the Link's OnClick and exclude the nested A (don't nest it otherwise React will nag you about it) and Button.
Basically we are dealing with a event bubbling here so might just use it to fine grain the behavior that we want. clicking anywhere inside the div will result to being routed to a page, while clicking any A or Button will not
<Link
to="/"
onClick={(e) => {
if (e.target !== e.currentTarget) {
if (["A", "BUTTON"].includes(e.target.nodeName)) {
e.preventDefault();
}
}
}}
>
<div>
Home
<br />
<button}>
HAIYAAA Don't Route me
</button>
<br />
<a href="#">
This is a link that is nested (Its not good to nest a!)
</a>
</div>
</Link>
Fiddle here: https://codesandbox.io/s/react-router-forked-4m4ww?file=/index.js
PS : ahh I spent time to learn something. Thanks for making my afternoon not a sleepy one
We need to stop the propagation of onClick event of the child to its parent.
<Link to="/">
<h1>Home</h1>
<button onClick={(e) => {
myNeededBehaviour();
e.stopPropagation();
}}>
HAIYAAA
</button>
</Link>
so, the stopPropagation will stop the event from propagating to its parent, and it will still calls myNeededBehaviour(); if you want, but the parent wont get the child's event. so it wont route, as it is not getting triggered.

How to create a button that opens a new page with the option to return back to previous page [ReactJS

Right below the page you see a 'back to log' button. If someone clicks on that it will return to the left page. So in order to do so I thought using react router will do the job. But not sure how to fix that.Is there someone who can help me to point me to the right direction. Keep in mind that it will not open a new tab!
Link to working snippet to understand the bigger picture of my app. CodeSandBox snippet here
return (
<div>
{info.map((show: any) => {
console.log(show.show)
return (
<div key={show.show.id}>
<ReactMarkdown source={show.show.name}/>
{show.show.image && <img src={show.show.image.medium}/>}
{show.show.genres.map((showGenre: string, index: number) => {
return (
<div key={index}>
<ReactMarkdown source={showGenre}/>
</div>
)
})}
<div>
<Router>
<ul>
<li>
<Link to="/">See deta</Link>
</li>
</ul>
</Router>
</div>
</div>
)
})}
</div>
)
Check out this working example (I placed notes in each file):
https://codesandbox.io/s/modest-panini-hkzlv?file=/src/App.js
Overview:
there are several ways to do this
my suggestion is to use the history npm and create a history.js file
you will also need to use Router from react-router-dom
in your parent component, or in a Context provider, you can store your state
in the parent component, use react-router-dom Switch and Route to place routes
depending on implementation, conditionally render show route for async state update
in your search component, place all your Links using react-router-dom
on click Links should also update app's state of your specific selection
this selection gets passed to the show route/component
in the show component attach an on click that uses history.goBack and resets state
this might help you:
this.props.history.goBack();
it goes back to prev page

Update dom without refresh the page in react 16

So, I've been looking for a way to render this img tag on my dom without refresh the screen. But I didn't find a definitive answer on how to do that! I mean, in a natural way, with react library and without change a lot of things.
So, when I click this div, it calls a method
<div ref={(ref) => this.refProjectImageCenter = ref} onClick={(e) => this.selectImage(e, this.refProjectImageCenter)} >
<img src="images/projects/new-account.png" alt="new account" />
</div>
And in this method, I update my state with a new img element (not sure if it's the best way to do it tho)
selectImage(e: any , el: HTMLDivElement)
{
e.preventDefault(); // This is not working
this.setState({ selected_img: <img src={el.children[0].getAttribute("src")} /> });
}
And the state will update this part of the DOM
<div className="image detail">
{this.state.selected_img}
</div>
It renders the img indeed, but the page flashes(refresh), and I want to do that asynchronously. It's possible to do that with react? If it's not, how everybody is doing it right now? Thanks a lot.
I found the problem Henry and Shubham. I was updating the css class of the main html tag:
this.refMasterDOM.classList.remove("active");
Inside the method componentWillUpdate(). I removed this line and it stopped refreshing the page with sestate command. Although I don't know why.

React does not recognize the `anyTouched` prop on a DOM element

i have redux form inside my reactstrap modal.when my popup appear,console log show below warning.without Form it's working charm.
You have a component say it's name is CustomComponent that retuns something like this
<div>
<Form {...this.props}>
<p> this.props.pText </p>
<Button>I'm a button named {this.props.buttonName} </Button>
</Form>
</div>
and when you render it in another file you do this
<CustomComponent pText="hi" buttonName="randomName">
so what happens is you are passing the buttomName, pText to your Form which doesn't accept pText, buttonName (remember, Your button & accept those props but not the form itself, so the virtual react DOM guesses that the prop is not for react, so it must be a real DOM prop & doesn't know what to do with it, to solve the problem, simply remove the {...this.props}
this is a result of how React is handling custom vs predefined DOM attributes -> see here
https://reactjs.org/warnings/unknown-prop.html

In ReactJS + Flux share a save button with many tabs

I have an strucure in a ReactComponent like
class MyComponent extends React.Component {
render() {
return (
<div class="row">
<MyMenuComponentTab></MyMenuComponentTab>
<Tab1></Tab1>
<Tab2></Tab2>
<Tab3></Tab3>
</div>
<div class="row">
<button onClick={this.handleButton}>SAVE</button>
</div>
)
}
}
In every tab you can create an independent entity in the backend, and every tab component is related with his own Store and Action in FLUX.
My question is if it's possible to makes the save button contextual? So if you press that button, it can handle in the function "handleButton" Action and Store is related.
The simplest alternative is to have embebed the save button in every tab, but isn't possible because of graphical design restrictions.
You could keep track of the active tab in the state of your MyComponent. Then, you could pass a callback to each Tab that changes the state to reflect which tab is active. That way, your handleButton function would only need to access this.state.activeTab to handle the save action in context.

Resources