Skip to content

Commit 6312174

Browse files
committed
improve how comments are fetched and rendered
1 parent f57e9ed commit 6312174

File tree

2 files changed

+56
-27
lines changed

2 files changed

+56
-27
lines changed

README.md

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,10 @@ Features that aren't checked below are yet to be implemented. If you want to imp
4646

4747
### TODO
4848

49-
- [ ] Add features not checked above
50-
- [ ] Fix and improve comment fetching.
51-
- Comments are fetched recursively due to Hacker News's API design, then flattened into an array where each reply is the next item in the array. This isn't a good solution for two reasons:
52-
1. The user has to wait for all the comments to be loaded before they can see any (`Promise.all()`).
53-
2. If a component unmounts (the user goes back to the feed), all the comments still get fetched, causing the JS thread to drop frames.
54-
- To fix this comments and comment replies should be fetched individually, appended to an array and the component will re render with the new comment added. If the component unmounts, simply stop fetching comments. The user will also be able to view comments almost immediately while others load.
49+
- [ ] Add features not implemented above
50+
- [x] Fix and improve comment fetching.
51+
- Comments are fetched recursively due to Hacker News's API design, then flattened into an array where each reply is the next item in the array. This isn't a good solution beacuse the user has to wait for all the comments to be loaded before they can see any (`Promise.all()`).
52+
- To fix this, each top comment and its replies should be fetched individually, appended to an array and the component will re render with the new comment added. The user will also be able to view comments almost immediately while others load.
5553
- [ ] Add caching for comments (older than 10 minutes), and posts. If post/comment requested again, check if in cache, if so load from cache.
5654

5755
### Run Locally

app/components/Post/AllComments.js

Lines changed: 52 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export default class AllComments extends React.Component {
2121
comments: null,
2222
error: null,
2323
loading: true,
24+
loadingMoreComments: false,
2425
refreshComments: false,
2526
};
2627
this.toggle = this.toggle.bind(this);
@@ -43,28 +44,54 @@ export default class AllComments extends React.Component {
4344

4445
fetchComments = () => {
4546
const { kids } = this.props.post;
46-
if (kids) {
47-
getComments(kids)
48-
.then(comments => {
49-
if (this._mounted) {
50-
this.setState({
51-
comments,
52-
loading: false,
53-
});
54-
}
55-
})
56-
.catch(error => {
57-
if (this._mounted) {
58-
this.setState({
59-
error,
60-
});
61-
}
62-
});
63-
} else {
47+
48+
if (!kids) {
6449
this.setState({
6550
comments: [],
6651
loading: false,
67-
})
52+
});
53+
return;
54+
}
55+
56+
for (let i = 0, p = Promise.resolve(); i < kids.length; i++) {
57+
p = p.then(_ => new Promise(resolve => {
58+
59+
// Get replies for current top level comment
60+
getComments([kids[i]])
61+
.then(comments => {
62+
let newComments = this.state.comments || [];
63+
newComments.push(...comments)
64+
65+
let loadingMoreComments = true;
66+
67+
// Last comment finished loading
68+
if (i == kids.length - 1) {
69+
loadingMoreComments = false;
70+
}
71+
72+
if (this._mounted) {
73+
this.setState({
74+
comments: newComments,
75+
loading: false,
76+
loadingMoreComments,
77+
}, () => {
78+
resolve();
79+
});
80+
} else {
81+
resolve();
82+
}
83+
})
84+
.catch(error => {
85+
if (this._mounted) {
86+
this.setState({
87+
error,
88+
loading: false,
89+
}, () => {
90+
resolve();
91+
});
92+
}
93+
});
94+
}));
6895
}
6996
};
7097

@@ -94,8 +121,7 @@ export default class AllComments extends React.Component {
94121
<View style={styles.allComments}>
95122
<FlatList
96123
data={this.state.comments}
97-
extraData={this.state.refreshComments}
98-
keyboardShouldPersistTaps='always'
124+
extraData={[this.state.refreshComments, this.state.comments]}
99125
keyExtractor={(item, index) => index.toString()}
100126
renderItem={({ item }) => (
101127
<Comment
@@ -110,6 +136,11 @@ export default class AllComments extends React.Component {
110136
/>
111137
)}
112138
/>
139+
{this.state.loadingMoreComments &&
140+
<View style={styles.loading}>
141+
<ActivityIndicator />
142+
</View>
143+
}
113144
</View>
114145
);
115146
}

0 commit comments

Comments
 (0)