Waiting for DY Script to Run and Ingest in ReactJS
I am working on a project where DOM manipulation using DY will just not work: updating components rendered by ReactJS.
A workaround for this is instead of manipulating the React's DOM is to attach data to a configuration variable that can be ingested into a react component and then used--when the DY experience fires. The challenge to this is React knowing when DY has fully loaded and the config settings are ready for React to use.
I have tried, which will work when there are multiple tests running on a page; it looks like this:
DY.API('callback', () => {
updateAppState(variable_set_by_dy);
});
My next try is the update the state on an event from DY since it's totally OK for the UI to re-render once we have data from the DY script available. So my real question is: what is the best way to fire an event and listen for it within a framework like React?
My other thought is to just fire a custom event once the js on DY has fired to avoid using promises with setTimeout, etc. Would this be a viable option or can I use a DY tool to actually wait for the js in dy to fully finish?
Thanks!
-
Hey Jordan,
The first and most important thing to do here is to make sure you are firing an SPA event every time there is an SPA transition. If this event doesn't get fired DY will assume it is still on the same page which will mean that no campaigns will be re-triggered.
Secondly it is important to make sure you toggle the `fire on every SPA` button on in each campaign you want to trigger through an SPA event. You can find this under advanced settings at the campaign level
You can find the details for the SPA event here.
If you already implemented the above steps you have a few options:
1. Wait for DY:
- One way to do this is with the callback event you mentioned above.
- Additionally, under `advanced` on the campaign level you can wait for `Dynamic Yield` which only allows the campaign to fire after all DY resources have been loaded
2. Wait n seconds:
- In the Advanced settings at the campaign level you can wait an `n` number of seconds before the campaign fires on the page
- Often with react certain implementations may scrub the DOM whenever they sense a state change. This function tends to timeout after about 3 seconds give or take. Waiting those three seconds may allow you to get the desired results.
If none of the above do what you are looking for feel free to comment again
-
Is this the same Saul that helped me onboard? :D If so, you rock and if it's not, you still rock :)
So, we aren't dealing with any virtual page views, interactivity or anything like that, so I don't think I need a SPA event; but can take a look at that, too.
Basically looking at:
- DY does some calculations and writes a variable to the window
- React sees the variable and goes, "cool, DY is running an experiment, so let's take that variable, put it into app state and then pass that down to all of our components that can use this extra data."
So really, we should only be nabbing this on the initial render or the re-render when React sees the data from DY, updates, and renders child components from there.
Wait for DY:
- What I found using the callback function is that this becomes unreliable if more than one test is running on a page. However, if there are some args I don't know about that can be passed to the callback function to know what experiment is running... That would be siiiiiick (or something I can dig into).
- I forgot about this option... I might look at this later, but ended up with an ok solution (albeit not by the dy books)
Wait n seconds:
- Right now I am firing once the page loads, so DY is firing after React which is fine for this case.
- Yep. This is the issue with manipulating React's dom. React audit's its virtual dom and things start to get rowdy quickly with a complex component. React thinks an element isn't there, but DY may have replaced it. Then it's a battle of conditional renders and dom traversal outside of React which is tedious.
What I ended up dialing in:
- I went ahead and made a custom event that passes the object that is made in the js of the DY template. I can update state when fired and pass it down to components from there. And this is working well without any weird race conditions since DY is the last thing to fire.
- It's not a pure DY solution, hahaa, but it is doing the job well enough without any weird effects; but I'll also dig more into how some of the DY tools (experiment more with these suggestions), too.
Thanks, Saul!!!
-
Hey Jordan,
I'm not sure if this will help you but I've had some success using mutationObservers to watch for DOM changes in a react app when it's not necessarily a full-page transition. Just make sure the observer is watching an element high enough up the DOM tree so it doesn't get wiped during a re-render. Again, it's not a purely DY solution but might be useful for you.
-
Thanks Dustin Neill for sharing - this hack is really interesting!
-
Dustin Neill Hahaha, so sorry, like a month later!
Thank you for this suggestion! I did not think to use mutation observers and will definitely keep this in mind. When using mutation observers, are you observing react components or possibly static elements on a page? We use portals to basically inject interactive components into statically rendered pages, so we have a combination of stating HTML + React elements.
=====================================================
The solution I went with works pretty well and will prolly use it to bridge more DY elements and React's app state. Basically using events/listeners to pass back data from say add to cart events (as an example) from DY to update app state.
Could also do something similar with observables (rxjs), as an idea for anyone interested (kinda tagging on Dustin's idea), but did not want to load up another lib. -
Jordan Tidwell I only use it on static elements on a page as more of a post-implementation method to avoid making changes to the code base. Your method sounds a lot more robust.
-
Hi Keren!
This is AWESOME to hear!
If there are any opportunities for beta testing or someway to get any features early, my team and I would be open to that for sure!
It is a challenge working with testing tools (not just a DY thing) that are geared up for traditional dom manipulation and making those work with any modern js framework. DY has definitely done more in strides to this regard (spa events) than other testing/personalization tools we've looked at, so to hear the DY team is extending these features is exciting.
Please sign in to leave a comment.
Comments
11 comments