Skip to content

Commit 245283b

Browse files
eschaeferlessp
authored andcommitted
feat: add trigger once option (#2)
Adds the possibility to add an `options`-record which currently only has `once` as a parameter. Thanks to @eschaefer!
1 parent 3af92b8 commit 245283b

File tree

4 files changed

+55
-5
lines changed

4 files changed

+55
-5
lines changed

Diff for: README.md

+15
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ Add `bs-react-is-visible` to `bs-dependencies` in `bsconfig.json`
2323

2424
## Usage
2525

26+
### Basic
27+
2628
```reason
2729
[@react.component]
2830
let make = () => {
@@ -34,6 +36,19 @@ let make = () => {
3436
};
3537
```
3638

39+
### With options
40+
41+
```reason
42+
[@react.component]
43+
let make = () => {
44+
let (isVisible, ref) = ReactIsVisible.useIsVisible(~options={once: true}, ());
45+
46+
<h1 ref>
47+
{(isVisible ? "I'm triggered as visible once!" : "I'm not visible") |> React.string}
48+
</h1>;
49+
};
50+
```
51+
3752
## Polyfill
3853

3954
[Browser compatibility.](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#Browser_compatibility)

Diff for: examples/App.re

+8-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,14 @@ let make = () => {
6464
style={Style.link(active === "lazyload")}>
6565
{"Lazy Load" |> React.string}
6666
</a>
67+
<a
68+
href="#triggeronce"
69+
title="TriggerOnce"
70+
onClick={_ => setActiveExample(_ => (<TriggerOnce />, "triggeronce"))}
71+
style={Style.link(active === "triggeronce")}>
72+
{"Trigger Once" |> React.string}
73+
</a>
6774
</nav>
6875
activeExample
6976
</div>;
70-
};
77+
};

Diff for: examples/TriggerOnce.re

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
module Style = {
2+
let fixed = ReactDOMRe.Style.make(~position="fixed", ~right="2rem", ());
3+
};
4+
5+
[@react.component]
6+
let make = () => {
7+
let (isVisible, ref) =
8+
ReactIsVisible.useIsVisible(~options={once: true}, ());
9+
10+
<div style=Basic.Style.wrapper>
11+
<h1> {"Scroll down" |> React.string} </h1>
12+
<h2 style=Style.fixed>
13+
{"Was triggered: " ++ string_of_bool(isVisible) ++ "" |> React.string}
14+
</h2>
15+
<div ref style={Basic.Style.box(isVisible)}>
16+
{(isVisible ? "I'm visible!" : "I'm not visible!") |> React.string}
17+
</div>
18+
</div>;
19+
};

Diff for: src/ReactIsVisible.re

+13-4
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,28 @@ module VO = {
1212
external getSubscribers: unit => 'subscriberList = "getSubscribers";
1313
};
1414

15-
let useIsVisible = () => {
15+
type options = {once: bool};
16+
let defaultOptions = {once: false};
17+
18+
let useIsVisible = (~options=defaultOptions, ()) => {
1619
let (isVisible, setIsVisible) = React.useState(() => false);
1720
let nodeRef = React.useRef(Js.Nullable.null);
1821

1922
React.useEffect0(() => {
20-
let handleVisibilityChange = entry =>
23+
let handleVisibilityChange = (el, entry) => {
2124
setIsVisible(_prevIntersecting => entry##isIntersecting);
2225

26+
if (entry##isIntersecting && options.once) {
27+
VO.unwatch(el);
28+
};
29+
};
30+
2331
let domElement =
2432
switch (nodeRef |> React.Ref.current |> Js.Nullable.toOption) {
2533
| Some(el) =>
26-
VO.watch(el, handleVisibilityChange);
34+
VO.watch(el, entry => handleVisibilityChange(el, entry));
2735
Some(el);
36+
2837
| None => None
2938
};
3039

@@ -35,4 +44,4 @@ let useIsVisible = () => {
3544
});
3645

3746
(isVisible, ReactDOMRe.Ref.domRef(nodeRef));
38-
};
47+
};

0 commit comments

Comments
 (0)