Skip to content

Commit 44ceb04

Browse files
committed
03-GraphQL Query with Apollo Client in React
1 parent 8377cbc commit 44ceb04

File tree

7 files changed

+183
-2
lines changed

7 files changed

+183
-2
lines changed

src/App/index.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import React, { Component } from 'react';
22

3+
import Profile from '../Profile';
4+
35
class App extends Component {
46
render() {
5-
return <div>Hello World</div>;
7+
return <Profile />;
68
}
79
}
810

9-
export default App;
11+
export default App;

src/Link/index.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import React from 'react';
2+
3+
const Link = ({ children, ...props }) => (
4+
<a {...props} target="_blank" rel="noopener noreferrer">
5+
{children}
6+
</a>
7+
);
8+
9+
export default Link;

src/Loading/index.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import React, { Component } from 'react';
2+
3+
import './style.css';
4+
5+
const TICK_RATE = 500;
6+
7+
class Loading extends Component {
8+
state = {
9+
dots: 0,
10+
};
11+
12+
componentDidMount() {
13+
this.interval = setInterval(this.onTick, TICK_RATE);
14+
}
15+
16+
componentWillUnmount() {
17+
clearInterval(this.interval);
18+
}
19+
20+
onTick = () => {
21+
this.setState(prevState => ({ dots: (prevState.dots + 1) % 4 }));
22+
};
23+
24+
render() {
25+
const { isCenter } = this.props;
26+
const { dots } = this.state;
27+
28+
const classNames = ['Loading'];
29+
30+
if (isCenter) {
31+
classNames.push('Loading_center');
32+
}
33+
34+
return (
35+
<div className={classNames.join(' ')}>
36+
<small>
37+
Loading {new Array(dots).fill(0).map(dot => '.')}
38+
</small>
39+
</div>
40+
);
41+
}
42+
}
43+
44+
export default Loading;

src/Profile/index.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import React from 'react';
2+
import gql from 'graphql-tag';
3+
import { Query } from 'react-apollo';
4+
5+
import RepositoryList from '../Repository';
6+
import Loading from '../Loading';
7+
8+
const GET_REPOSITORIES_OF_CURRENT_USER = gql`
9+
{
10+
viewer {
11+
repositories(
12+
first: 5
13+
orderBy: { direction: DESC, field: STARGAZERS }
14+
) {
15+
edges {
16+
node {
17+
id
18+
name
19+
url
20+
descriptionHTML
21+
primaryLanguage {
22+
name
23+
}
24+
owner {
25+
login
26+
url
27+
}
28+
stargazers {
29+
totalCount
30+
}
31+
viewerHasStarred
32+
watchers {
33+
totalCount
34+
}
35+
viewerSubscription
36+
}
37+
}
38+
}
39+
}
40+
}
41+
`;
42+
43+
const Profile = () => (
44+
<Query query={GET_REPOSITORIES_OF_CURRENT_USER}>
45+
{({ data, loading }) => {
46+
const { viewer } = data;
47+
48+
if (loading || !viewer) {
49+
return <Loading />;
50+
}
51+
52+
return <RepositoryList repositories={viewer.repositories} />;
53+
}}
54+
</Query>
55+
);
56+
57+
export default Profile;
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import React from 'react';
2+
3+
import Link from '../../Link';
4+
5+
import '../style.css';
6+
7+
const RepositoryItem = ({
8+
name,
9+
url,
10+
descriptionHTML,
11+
primaryLanguage,
12+
owner,
13+
stargazers,
14+
watchers,
15+
viewerSubscription,
16+
viewerHasStarred,
17+
}) => (
18+
<div>
19+
<div className="RepositoryItem-title">
20+
<h2>
21+
<Link href={url}>{name}</Link>
22+
</h2>
23+
24+
<div className="RepositoryItem-title-action">
25+
{stargazers.totalCount} Stars
26+
</div>
27+
</div>
28+
29+
<div className="RepositoryItem-description">
30+
<div
31+
className="RepositoryItem-description-info"
32+
dangerouslySetInnerHTML={{ __html: descriptionHTML }}
33+
/>
34+
<div className="RepositoryItem-description-details">
35+
<div>
36+
{primaryLanguage && (
37+
<span>Language: {primaryLanguage.name}</span>
38+
)}
39+
</div>
40+
<div>
41+
{owner && (
42+
<span>
43+
Owner: <a href={owner.url}>{owner.login}</a>
44+
</span>
45+
)}
46+
</div>
47+
</div>
48+
</div>
49+
</div>
50+
);
51+
52+
export default RepositoryItem;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import React from 'react';
2+
3+
import RepositoryItem from '../RepositoryItem';
4+
5+
import '../style.css';
6+
7+
const RepositoryList = ({ repositories }) =>
8+
repositories.edges.map(({ node }) => (
9+
<div key={node.id} className="RepositoryItem">
10+
<RepositoryItem {...node} />
11+
</div>
12+
));
13+
14+
export default RepositoryList;

src/Repository/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import RepositoryList from './RepositoryList';
2+
3+
export default RepositoryList;

0 commit comments

Comments
 (0)