A React app designed like Dcard with Bootstrap that could:
- search users/organizations on GitHub
- list user's/organization's all repositories with
Infinite Scroll
from GitHub REST API - read repository's detail from GitHub REST API
- follow or unfollow a user/organization which data store in
localStorage
Doc:Dcard 2022 Web Frontend Intern Homework.pdf
Blog:Dcard 面試|應徵 Web Frontend Intern 實習經驗分享!
作業看的出來很用心,特別去研究了 Dcard 的 UI,體驗上也大致不錯,多做追蹤等功能也相當有特色,README 文件的詳細程度也很加分。
- How To Use
- Architecture Design & Explanation
- index.js:for direct route
- Home.js:for search a GitHub username & list all following users
- UserPage.js:for display GitHub user & his/her all repositories
- RepoDetail.js:for display repository details
- Components:used not only on one page
- Learn More
- LICENSE:MIT
🎊 This React app had deployed on GitHub page, you could try it on 5j54d93.github.io/Dcard-2022-Web-Frontend-Intern-Homework!
-
Your computer should have downloaded Node.js before(Node >= 14.0.0 and npm >= 5.6)
-
Download this repository via
git clone
or from Releases
git clone https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework
- Change directories to this repository via
cd
or drag this folder and drop in terminal
cd Dcard-2022-Web-Frontend-Intern-Homework
- Run this React app
npm install
npm start
npm start
will automatically open http://localhost:3000 on your computer.
index.js:for direct route
- every page will have Navbar and Footer
- Home:route at
/
- UserPage:route at
/users/{username}/repos
- RepoDetail:route at
/users/{username}/repos/{repo}
ReactDOM.render(
<React.StrictMode>
<div className='d-flex flex-column min-vh-100'>
<Navbar />
<BrowserRouter>
<Routes>
<Route path='/' element={<Home />} />
<Route path='/users/:owner/repos' element={<UserPage />} />
<Route path='/users/:owner/repos/:repo' element={<RepoDetail />} />
</Routes>
</BrowserRouter>
<Footer />
</div>
</React.StrictMode>,
document.getElementById('root')
);
Home.js:for search a GitHub username & list all following users
SearchBar()
- a search bar for user to input GitHub username
- can't submit if there's no input
- use
useRef()
to prevent re-render while user is typing - prepare data
onSubmit
before navigate toUserPage
to ensure thatUserPage
will already have data to show on first render(won't render twice) - store data that fetch from API in
sessionStorage
to prevent API recall if we need the same data later
FollowingUsers()
- list all following users stored in
localStorage
- prepare data
onClick
before navigate toUserPage
to ensure thatUserPage
will already have data to show on first render(won't render twice) - store data that fetch from API in
sessionStorage
to prevent API recall if we need the same data later
- list all following users stored in
UserPage.js:for display GitHub user & his/her all repositories
- first check data we need had already saved in
sessionStorage
- if yes(get this page from
Home
orRepoDetail
):get data fromsessionStorage
- else(get this page via link directly):fetch data from API call and save it in
sessionStorage
- GitHub User:
GET /users/{username}
- Repos:
GET /users/{username}/repos
- render
Loading
while API call
- GitHub User:
- if yes(get this page from
- check data in
sessionStorage
- if username isn't exit:show「No Such User」
- else if number of user's public repo=0:show「Haven't created any repository yet」
- else:show
RepoList
- else:show
{userData.message === 'Not Found'
? <div className={`fs-3 text-center ${styles.textMiddleBlue}`}>No Such User.</div>
: userData.public_repos === 0
? <div className={`fs-3 text-center ${styles.textMiddleBlue}`}>Haven't created any repository yet.</div>
: <RepoList />
}
Differences between user and organization:
User | Organization | |
---|---|---|
info | num of repos、num of followers | location、blog link |
tag above RepoList |
"All Public Repositories" | ".public_repos Public Repositories" |
RepoList()
- use
useRef()
&IntersectionObserver
on ProgressView to achieve infinite scroll without always listening towindow.innerHeight
、document.documentElement.scrollTop
、document.documentElement.offsetHeight
- store repos data in
sessionStorage
, so when user go toRepoDetail
and back, we won't re-fetch data from API - use
window.scrollTo()
to ensure that when user go toRepoDetail
and back, the position ofUserPage
will be the same of previous position(won't go back to top)- because
window.scrollTo()
default with animation in Chrome, we usebehavior: 'instant'
to prevent that for better user experience
- because
- use
window.scrollTo({
top: sessionStorage.getItem('offsetY'),
left: 0,
behavior: 'instant'
});
RepoRow()
- use
React.memo
to prevent re-render everyRepoRow()
inRepoList()
, only render the next 10 new repos or less in infinite scroll! - prepare data
onClick
before navigate toRepoDetail
to ensure thatRepoDetail
will already have data to show on first render(won't render twice) - store data that fetch from API in
sessionStorage
to prevent API recall if we need the same data later- we also save
document.documentElement.scrollTop
insessionStorage
onClick
- we also save
- use
RepoDetail.js:for display repository details
- first check data we need had already saved in
sessionStorage
- if yes(get this page from
UserPage
):get data fromsessionStorage
- else(get this page via link directly):fetch data from API call and save it in
sessionStorage
- GitHub User:
GET /users/{username}
- Repo Data:
GET /repos/{owner}/{repo}
- render
Loading
while API call
- GitHub User:
- if yes(get this page from
- Click right-bottom GitHub icon could go to repository page on GitHub
Components:used not only on one page
CreateTime.js
- use
memo
to prevent re-render - reusable:use
props.displayTime
to display- day month year on
RepoRow
- day month year time on
RepoDetail
- day month year on
- use
IconGroup.js
- use
memo
to prevent re-render
- use
FollowButton.js
- return Following or Follow depends on wether the username is saved in
localStorage
- save or delete user data in
localStorage
while the buttononClick
- return Following or Follow depends on wether the username is saved in
With access tokens, GitHub Rest API Rate Limit could up to 5000 requests per hour. But because this is a public repo and our React app is depolied on Github page, we couldn't use token(GitHub will delete token if it detect that we commit it). Rate Limit will only up to 60 requests per hour!For more information, view this official doc.
I've used token like below when this repo is private, and the token won't remove itself!
const response = await fetch(URL, {
headers: {
Authorization: 'token TOKEN'
}
});
Thanks to Bootstrap, our React app could response well on every different devices!
- Truncate Navbar title into「...」
- smaller
padding
with@media (max-width: 760px)
- somewhere
flex-wrap
, like:FollowButton
、GitHub Icon、Topics
This package is MIT licensed.