-
Notifications
You must be signed in to change notification settings - Fork 783
refactor: migrate search screen to the new API #758
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
refactor: migrate search screen to the new API #758
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left some comments to explain normalizrKey
response, | ||
nextPageUrl: this.getNextPageUrl(response), | ||
schema: Schemas.REPO_ARRAY, | ||
normalizrKey: 'items', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the first use of normalizrKey
.
The API response for this call looks like the following:
{
total_count: 645354,
incomplete_results: false,
items: [
{ /* first repo object */},
{ /* second repo object */},
...
]
}
We only care for what's inside items, the array of repositories.
normalizrKey
tells the dispatch proxy to only treat that property of the JSON, instead of all the JSON.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NICE ⭐️
const SearchTypes = { | ||
REPOS: 0, | ||
USERS: 1, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
introduced this little enum to make the code more readable
|
||
const reposSearchResultsPagination = SEARCH_REPOS[searchQuery] || { | ||
ids: [], | ||
isFetching: false, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
contrarily to other PRs, when we're loading this screen, we're not fetching yet, so we set isFetching
to false.
@@ -127,19 +161,22 @@ class Search extends Component { | |||
const selectedSearchType = | |||
selectedType !== null ? selectedType : this.state.searchType; | |||
|
|||
if (query !== '') { | |||
if (query.trim() !== '') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a trim() here. Currently, if you search for " ", the app will crash!
@@ -127,19 +161,22 @@ class Search extends Component { | |||
const selectedSearchType = | |||
selectedType !== null ? selectedType : this.state.searchType; | |||
|
|||
if (query !== '') { | |||
if (query.trim() !== '') { | |||
const searchedQuery = query.toLowerCase(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GitHub search is case insensitive. We lowercase the query string in order to avoid having two paginations for nothing (Gitpoint vs gitpoint)
src/search/screens/search.screen.js
Outdated
}); | ||
if (selectedSearchType === 0) { | ||
searchRepos(query); | ||
this.props.navigation.setParams({ [NAV_QUERY_PARAM]: searchedQuery }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We save the query string in the navigation, to be able to get it in MapStateToProps and select the corresponding pagination
src/search/screens/search.screen.js
Outdated
].nextPageUrl === null | ||
) { | ||
return null; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here, we conditionally select the good pagination.
I can brake the code to have something less barbaric. This will change anyways when we introduce Code & Wikis search
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just wondering, how are you thinking we can simplify this when code & wikis are introduced?
Also, in the meantime, maybe we can simplify the following to something like:
renderFooter = () => {
const { searchType } = this.state;
const { reposSearchResultsPagination, usersSearchResultsPagination } = this.props;
const currResultsPagination = searchType === SearchTypes.REPOS ? reposSearchResultsPagination : usersSearchResultsPagination;
if (currResultsPagination.nextPageUrl) {
return (
<View
style={{
paddingVertical: 20,
}}
>
<ActivityIndicator animating size="large" />
</View>
);
}
};
And another thought (if not know) - maybe we can extract this to a separate component (<LoadingFooter />
?) if this logic is duplicated exactly the same in multiple screens?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking about having getActiveResultsPagination()
& getActiveResults()
instead of using ifs everywhere.
And for the refactoring, I was thinking of:
- a
<PaginatedFlatList>
which would take apagination
prop and do everything for us. - a
getPagination()
in utils to avoid this chunk of code in mapStateToProps:
const reposSearchResultsPagination = SEARCH_REPOS[searchQuery] || {
ids: [],
isFetching: false,
}
was just holding off on changing stuff until I got a few PRs merged. I think I'll do that next
src/search/screens/search.screen.js
Outdated
? 'searchRepos' | ||
: 'searchUsers' | ||
](query, { loadMore: true }) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same remark as above.
@@ -4,7 +4,6 @@ import { userReducer } from 'user'; | |||
import { repositoryReducer } from 'repository'; | |||
import { organizationReducer } from 'organization'; | |||
import { issueReducer } from 'issue'; | |||
import { searchReducer } from 'search'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pew pew pew 🔫
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aside from one tiny thing, great stuff fam.
I'm excited, you're improving every screen in this app and simplifying our entire Redux store in the same time <3
src/search/screens/search.screen.js
Outdated
].nextPageUrl === null | ||
) { | ||
return null; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just wondering, how are you thinking we can simplify this when code & wikis are introduced?
Also, in the meantime, maybe we can simplify the following to something like:
renderFooter = () => {
const { searchType } = this.state;
const { reposSearchResultsPagination, usersSearchResultsPagination } = this.props;
const currResultsPagination = searchType === SearchTypes.REPOS ? reposSearchResultsPagination : usersSearchResultsPagination;
if (currResultsPagination.nextPageUrl) {
return (
<View
style={{
paddingVertical: 20,
}}
>
<ActivityIndicator animating size="large" />
</View>
);
}
};
And another thought (if not know) - maybe we can extract this to a separate component (<LoadingFooter />
?) if this logic is duplicated exactly the same in multiple screens?
@housseindjirdeh refactoring done, now our render() method doesn't check for the search type anymore (aside for a translation) 🙌 Adding a new search type should be as simple as declaring it in the enum and the switch/case in the new methods. I also spotted and fixed a minor UI problem, where the Loading list footer was displayed during the first search, resulting in two Loaders being displayed. |
By the way, noticed a bad UX design. Having a single FlatList to handle the various search type results may not be a good idea: If you search for "react", display results for Repositories and Users, then scroll down on Repositories, when you get back to the Users tab, the list will have been scrolled. Something to address in another PR. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So so great, thank you so much 🚀
And aaah I've never caught that before :( That really isn't great behaviour - opened #764 for this |
Description
Refactored the search screen to make use of the new API. Search results are now paginated & cached!