-
Notifications
You must be signed in to change notification settings - Fork 66
/
TopStoriesPage.re
executable file
·81 lines (74 loc) · 2.05 KB
/
TopStoriesPage.re
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
open Belt;
open Utils;
type state = {
topstories: StoryData.topstories,
page: int,
loading: bool,
};
type action =
| Loaded((int, StoryData.topstories))
| Loading;
let initialState = {topstories: [||], page: 0, loading: false};
[@react.component]
let make = () => {
let (state, dispatch) =
React.useReducer(
(state, action) =>
switch (action) {
| Loading => {...state, loading: true}
| Loaded((page, data)) =>
let updatedTopstories = Array.concat(state.topstories, data);
{topstories: updatedTopstories, page: page + 1, loading: false};
},
initialState,
);
// Using useEffect0 to run this effect one time and prevent multiple reloads of same data which crashes browser
React.useEffect0(() => {
StoryData.fetchTopStories(state.page, payload =>
dispatch(Loaded(payload))
)
|> ignore;
None;
});
React.useEffect(() => {
let nearTheBottom = () => distanceFromBottom() < 100;
let loadNextPage = () =>
if (state.page < 4) {
StoryData.fetchTopStories(state.page, payload =>
dispatch(Loaded(payload))
)
|> ignore;
dispatch(Loading);
};
let scrollHander = _e =>
if (nearTheBottom() && !state.loading) {
loadNextPage();
};
Webapi.Dom.window
|> Webapi.Dom.Window.addEventListener("scroll", scrollHander);
Some(
() =>
Webapi.Dom.window
|> Webapi.Dom.Window.removeEventListener("scroll", scrollHander),
);
});
<div>
{if (Array.length(state.topstories) > 0) {
state.topstories
->(
Array.mapWithIndex((index, story)
/* key must be a unique string attached to the story, DO NOT use index. Using just the story.id get error in browser for duplicate keys*/
=>
<StoryListItem
key={string_of_int(story.id + index)}
index
story
/>
)
)
->React.array;
} else {
ReasonReact.null;
}}
</div>;
};