Joseph Astrahan
Joseph Astrahan

Reputation: 9072

Trigger click event for react element

I'm trying to simulate a click using the developer console for a react element. For making it easy for you guys to test instead of using my code, use the following react website https://www.tradingview.com/chart/?symbol=COINBASE%3ABTCUSD

This occurs on other websites like Facebook as well on some items. This is just an easy no login site to test.

The section I'm trying to click is an item in the watchlist. In the picture below I put an arrow pointing to it. The particular menu appears when you click the button above the alarm clock icon in the far upper right of the screen under the 'Start free trial' blue buton.

enter image description here

To understand what I expect to happen, try clicking on any of the columns in the row, like SPX, NDQ, DJI, etc... (you should see the page and stock graph change)

I can 'sort' of simulate a click currently, but all it does is highlight the row but not actually change the page like when you perform an actual click.

To see what I mean, press F12 to open the developer console and type a command like below.

document.getElementsByClassName("wrap-XdW9S1Ib")[2].dispatchEvent(new Event('click',{bubbles:true}));

enter image description here

The class name might be different for you, so you might have to hunt around in the element menu of the developer console to find out what it is for you. Do a search for the word wrap- and you should eventually find the right set of classes.

In the picture I uploaded you will notice that the click event triggers a blue background around the NDQ (since that is the '3rd' element of the wrap class). Note that it DID NOT change the actual page and stock graph however.

I have tried sending other events like 'input', 'select', 'submit', 'dblclick' to no avail. I have tried clicking sub elements of that wrapper as well, every single one with no luck.

My goal is to get it to simulate the click and actually get it to change the page as a result of that click.

What am I doing wrong with my current approach?

Upvotes: 1

Views: 4389

Answers (2)

Rob M
Rob M

Reputation: 1

When I try this I get an error:

Uncaught TypeError: document.querySelector(...).__reactProps$6jhf67fyckh.onClick is not a function

I am doing this in the Chrome Dev console. the document.querySelector(path) is autocompleting the __reactProps which displays:

document.querySelector("#root > div > div > div.sc-hQRsPl.bqPigl > div > div.sc-papXJ.iIImKA > form > div:nth-child(9) > input").__reactProps$6jhf67fyckh
{value: 'Redeem', disabled: false, type: 'submit', className: 'sc-jZiqTT izoCLX'}
className: "sc-jZiqTT izoCLX"
disabled: false
type: "submit"
value: "Redeem"
[[Prototype]]: Object

Also, as the __reactPops$6jhf67fyckh appears to be generated each time, is it possible to grab this some other way?

Upvotes: 0

Joseph Astrahan
Joseph Astrahan

Reputation: 9072

Okay so I figured it out. It turns out that react is very picky about the events being isTrusted: true AND it also needs a property nativeEvent : {detail:1}

So this will be complicated but to simulate the click correctly you have to first identify where the 'onClick' react element is.

In my case the element was the <div class="wrap-XdW9S1Ib" draggable="true"> from my tradingview example.

Thanks to the handy command monitorEvents($0,"click") which you can type in the console it will record all clicks for the last selected item in the elements tab view.

Using this you can type something like: var elem = $0; to easily set the element, or you can just select it like how I did in my question.

Next, a key thing to understand is that the isTrusted property of events is there to determine if the click was a genuine click or not. This is why elem.click() will not work!

So how do we get around this?

By putting a click event manually on top and recording the event to a global variable called event!

var event;
elem.addEventListener("click",function(e){console.log("click detected");event=e});

The key here is event=e to store it to the global variable. Now doing this alone is not enough, as if you call elem.click() this will just simply call both click events and it still will not work.

But, REACT works using synthetic events and takes the 'event' object to work with to pass on its data.

Therefore, if you know where its true onClick event is that supercedes the usual onclick you can call it directly with this isTrusted: true event.

Type a command like this to find the __reactProps for the object.

for(key in elem){console.log(key)}

This will print out all the objects. In my case onClick was hiding inside of elem.__reactProps$3jcigo40r49

Now simply call:

elem.__reactProps$3jcigo40r49.onClick(event);

and it will correctly treat it like an actual mouse click and trigger all the changes as you would expect. Except... wait, it still didn't work cause you get an error saying Cannot read properties of undefined (reading 'detail').

To fix this simply say in console.

event.nativeEvent = {detail:1}

Now try the previous command again and it will work!


EDIT -- Even easier Answer Below

Turns out there is an even easier solution.

It appears that in my case isTrusted does not matter. It was the nativeEvent: {details:1} that did.

Simply create a new pointer event like this.

var testEvent = new PointerEvent("click");
testEvent.nativeEvent = {detail:1}
elem.__reactProps$3jcigo40r49.onClick(testEvent);

3 lines of code and you can click!

Upvotes: 2

Related Questions