-
Notifications
You must be signed in to change notification settings - Fork 123
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fire track event when element becomes visible #107
Comments
Hey @dhruvg thanks for the kudos, that's appreciated and I'm glad you're making good use of react-tracking 😁 So for this use case, you actually have a few options. Visibility is driven by propsIf the visibility of the component is driven by the parent, and thus, by props, then you can actually optionally dispatch a tracking call by returning a falsy value initially and then the object to dispatch when the "show" prop is toggled. Something like: @track(props => props.hidden ? false : ({ button: props.id }))
class MyButton extends PureComponent { ... } Although in this case it's probably better to just have the parent not render the component until it should be shown, but it depends where the visibility logic exists. Visibility is driven by stateIf, instead, the component itself manages its own hidden/shown state, then I think you should be able to do something similar: @track(props => ({ button: props.id }))
class MyButton extends Component {
// return obj for dispatch while state.hidden is true because we're about to flip it
@track((props, state) => state.hidden ? ({ event: 'button.show' )} : false)
toggleState() {
this.setState({ hidden: !this.state.hidden })
}
...
} Visibility determined by physical visibility in the viewportThis is when an external library, like @rsearchgate/react-intersection-observer (or the straight IntersectionObserver API) can be used. import React, { Component } from 'react';
import 'intersection-observer'; // optional polyfill
import Observer from '@researchgate/react-intersection-observer';
import track from 'react-tracking';
@track(props => ({ button: props.id })
class MyButton extends Component {
@track({ event: 'button.show' })
handleIntersection(event) {
console.log(event.isIntersecting);
}
render() {
const options = {
onChange: this.handleIntersection,
root: '#scrolling-container',
rootMargin: '0% 0% -25%',
};
return (
<div id="scrolling-container" style={{ overflow: 'scroll', height: 100 }}>
<Observer {...options}>
<div>I am the target element</div>
</Observer>
</div>
);
}
} Of course, this would require an IntersectionObserver polyfill for some browsers. As you can see the use cases for what "visible" means can be very different depending on use case. And even if we can agree that visibility means visible in the viewport, even that can be variable (e.g. how close to the viewport, any buffer? etc). So I hesitate to include this as a built-in feature to react-tracking, but the primitives are there. Additionally, you could build your own HoC wrapper that encompasses this logic if visibility means the same thing for your app everywhere. Something like a Hope that's helpful! |
Thanks for the in-depth response. I am aiming for the visibility in viewport option. I will give the external lib + HoC a shot. |
First off, thanks for making this. I have been using react-tracking for a few months now and it's so clean while getting me the granularity of tracking I desire. Kudos.
I am curious how users of this library check for component visibility before firing an event. A simple use case is that I have a hidden alert on the page. I want to fire a "show" event when this alert becomes visible (not when it is mounted). This use case is pretty common -- think modals, buttons which are invisible on small screens but become visible on large screens, etc...
So far, the best I have come up with is to use an external library to track component visibility and combine that with react-tracking to fire events then the component becomes visible. But it's clunky. I am envisioning something like this instead:
Thoughts?
The text was updated successfully, but these errors were encountered: