Skip to content

Commit 51cbfae

Browse files
committed
(chore) - convert to urql
1 parent e677814 commit 51cbfae

File tree

13 files changed

+379
-413
lines changed

13 files changed

+379
-413
lines changed

package.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"@urql/exchange-graphcache": "^1.0.0-beta.3",
77
"@urql/exchange-suspense": "^0.1.0",
88
"graphql": "14.5.3",
9+
"graphql-tag": "^2.10.1",
910
"react": "16.9.0",
1011
"react-dom": "16.9.0",
1112
"react-router": "5.0.1",
@@ -19,5 +20,17 @@
1920
"build": "react-scripts build",
2021
"test": "react-scripts test --env=jsdom",
2122
"eject": "react-scripts eject"
23+
},
24+
"browserslist": {
25+
"production": [
26+
">0.2%",
27+
"not dead",
28+
"not op_mini all"
29+
],
30+
"development": [
31+
"last 1 chrome version",
32+
"last 1 firefox version",
33+
"last 1 safari version"
34+
]
2235
}
2336
}

server/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
},
99
"dependencies": {
1010
"bcryptjs": "^2.4.3",
11-
"graphql": "^14.5.3",
1211
"graphql-yoga": "^1.18.3",
1312
"jsonwebtoken": "^8.5.1",
1413
"prisma-client-lib": "^1.31.0"

server/yarn.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1733,7 +1733,7 @@ graphql-yoga@^1.18.3:
17331733
dependencies:
17341734
iterall "^1.2.2"
17351735

1736-
graphql@^14.3.0, graphql@^14.5.3:
1736+
graphql@^14.3.0:
17371737
version "14.5.3"
17381738
resolved "https://registry.yarnpkg.com/graphql/-/graphql-14.5.3.tgz#e025851cc413e153220f4edbbb25d49f55104fa0"
17391739
integrity sha512-W8A8nt9BsMg0ZK2qA3DJIVU6muWhxZRYLTmc+5XGwzWzVdUdPVlAAg5hTBjiTISEnzsKL/onasu6vl3kgGTbYg==

src/components/App.js

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,27 @@
1-
import React, { Component } from 'react'
1+
import React from 'react'
22
import LinkList from './LinkList'
33
import CreateLink from './CreateLink'
44
import Header from './Header'
55
import { Switch, Route, Redirect } from 'react-router-dom'
66
import Login from './Login'
77
import Search from './Search'
88

9-
class App extends Component {
10-
render() {
11-
return (
12-
<div className="center w85">
13-
<Header />
14-
<div className="ph3 pv1 background-gray">
15-
<Switch>
16-
<Route exact path="/" render={() => <Redirect to="/new/1" />} />
17-
<Route exact path="/create" component={CreateLink} />
18-
<Route exact path="/login" component={Login} />
19-
<Route exact path="/search" component={Search} />
20-
<Route exact path="/top" component={LinkList} />
21-
<Route exact path="/new/:page" component={LinkList} />
22-
</Switch>
23-
</div>
24-
</div>
25-
)
26-
}
27-
}
9+
const App = () => (
10+
<div className="center w85">
11+
<Header />
12+
<div className="ph3 pv1 background-gray">
13+
<React.Suspense fallback={<p>Fetching</p>}>
14+
<Switch>
15+
<Route exact path="/" render={() => <Redirect to="/new/1" />} />
16+
<Route exact path="/create" component={CreateLink} />
17+
<Route exact path="/login" component={Login} />
18+
<Route exact path="/search" component={Search} />
19+
<Route exact path="/top" component={LinkList} />
20+
<Route exact path="/new/:page" component={LinkList} />
21+
</Switch>
22+
</React.Suspense>
23+
</div>
24+
</div>
25+
);
2826

2927
export default App

src/components/CreateLink.js

Lines changed: 38 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
import React, { Component } from 'react'
2-
import { Mutation } from 'react-apollo'
1+
import React from 'react'
2+
import { useMutation } from 'urql'
33
import gql from 'graphql-tag'
4-
import { FEED_QUERY } from './LinkList'
5-
import { LINKS_PER_PAGE } from '../constants'
4+
import usePreviousValue from '../hooks/usePreviousValue';
65

76
const POST_MUTATION = gql`
87
mutation PostMutation($description: String!, $url: String!) {
@@ -15,57 +14,43 @@ const POST_MUTATION = gql`
1514
}
1615
`
1716

18-
class CreateLink extends Component {
19-
state = {
20-
description: '',
21-
url: '',
22-
}
17+
const CreateLink = ({ history }) => {
18+
const [description, setDescription] = React.useState("");
19+
const [url, setUrl] = React.useState('');
20+
const [state, executeMutation] = useMutation(POST_MUTATION);
21+
const prevFetching = usePreviousValue(state.fetching);
22+
23+
React.useEffect(() => {
24+
if (state.fetching === false && prevFetching === true) {
25+
history.push('/new/1')
26+
}
27+
}, [state.fetching, prevFetching, history]);
2328

24-
render() {
25-
const { description, url } = this.state
26-
return (
27-
<div>
28-
<div className="flex flex-column mt3">
29-
<input
30-
className="mb2"
31-
value={description}
32-
onChange={e => this.setState({ description: e.target.value })}
33-
type="text"
34-
placeholder="A description for the link"
35-
/>
36-
<input
37-
className="mb2"
38-
value={url}
39-
onChange={e => this.setState({ url: e.target.value })}
40-
type="text"
41-
placeholder="The URL for the link"
42-
/>
43-
</div>
44-
<Mutation
45-
mutation={POST_MUTATION}
46-
variables={{ description, url }}
47-
onCompleted={() => this.props.history.push('/new/1')}
48-
update={(store, { data: { post } }) => {
49-
const first = LINKS_PER_PAGE
50-
const skip = 0
51-
const orderBy = 'createdAt_DESC'
52-
const data = store.readQuery({
53-
query: FEED_QUERY,
54-
variables: { first, skip, orderBy },
55-
})
56-
data.feed.links.unshift(post)
57-
store.writeQuery({
58-
query: FEED_QUERY,
59-
data,
60-
variables: { first, skip, orderBy },
61-
})
62-
}}
63-
>
64-
{postMutation => <button onClick={postMutation}>Submit</button>}
65-
</Mutation>
29+
const postMutation = React.useCallback(() => {
30+
executeMutation({ url, description });
31+
}, [url, description, executeMutation]);
32+
33+
return (
34+
<div>
35+
<div className="flex flex-column mt3">
36+
<input
37+
className="mb2"
38+
value={description}
39+
onChange={e => setDescription(e.target.value)}
40+
type="text"
41+
placeholder="A description for the link"
42+
/>
43+
<input
44+
className="mb2"
45+
value={url}
46+
onChange={e => setUrl(e.target.value)}
47+
type="text"
48+
placeholder="The URL for the link"
49+
/>
6650
</div>
67-
)
68-
}
51+
<button onClick={postMutation}>Submit</button>
52+
</div>
53+
);
6954
}
7055

7156
export default CreateLink

src/components/Header.js

Lines changed: 43 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,53 @@
1-
import React, { Component } from 'react'
1+
import React from 'react'
22
import { Link } from 'react-router-dom'
33
import { withRouter } from 'react-router'
44
import { AUTH_TOKEN } from '../constants'
55

6-
class Header extends Component {
7-
render() {
8-
const authToken = localStorage.getItem(AUTH_TOKEN)
9-
return (
10-
<div className="flex pa1 justify-between nowrap orange">
11-
<div className="flex flex-fixed black">
12-
<div className="fw7 mr1">Hacker News</div>
13-
<Link to="/" className="ml1 no-underline black">
14-
new
15-
</Link>
16-
<div className="ml1">|</div>
17-
<Link to="/top" className="ml1 no-underline black">
18-
top
19-
</Link>
20-
<div className="ml1">|</div>
21-
<Link to="/search" className="ml1 no-underline black">
22-
search
6+
const Header = ({ history }) => {
7+
const authToken = localStorage.getItem(AUTH_TOKEN)
8+
return (
9+
<div className="flex pa1 justify-between nowrap orange">
10+
<div className="flex flex-fixed black">
11+
<div className="fw7 mr1">Hacker News</div>
12+
<Link to="/" className="ml1 no-underline black">
13+
new
14+
</Link>
15+
<div className="ml1">|</div>
16+
<Link to="/top" className="ml1 no-underline black">
17+
top
18+
</Link>
19+
<div className="ml1">|</div>
20+
<Link to="/search" className="ml1 no-underline black">
21+
search
22+
</Link>
23+
{authToken && (
24+
<div className="flex">
25+
<div className="ml1">|</div>
26+
<Link to="/create" className="ml1 no-underline black">
27+
submit
28+
</Link>
29+
</div>
30+
)}
31+
</div>
32+
<div className="flex flex-fixed">
33+
{authToken ? (
34+
<div
35+
className="ml1 pointer black"
36+
onClick={() => {
37+
localStorage.removeItem(AUTH_TOKEN)
38+
history.push(`/`)
39+
}}
40+
>
41+
logout
42+
</div>
43+
) : (
44+
<Link to="/login" className="ml1 no-underline black">
45+
login
2346
</Link>
24-
{authToken && (
25-
<div className="flex">
26-
<div className="ml1">|</div>
27-
<Link to="/create" className="ml1 no-underline black">
28-
submit
29-
</Link>
30-
</div>
3147
)}
32-
</div>
33-
<div className="flex flex-fixed">
34-
{authToken ? (
35-
<div
36-
className="ml1 pointer black"
37-
onClick={() => {
38-
localStorage.removeItem(AUTH_TOKEN)
39-
this.props.history.push(`/`)
40-
}}
41-
>
42-
logout
43-
</div>
44-
) : (
45-
<Link to="/login" className="ml1 no-underline black">
46-
login
47-
</Link>
48-
)}
49-
</div>
5048
</div>
51-
)
52-
}
49+
</div>
50+
)
5351
}
5452

5553
export default withRouter(Header)

src/components/Link.js

Lines changed: 30 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import React, { Component } from 'react'
1+
import React from 'react'
22
import { AUTH_TOKEN } from '../constants'
33
import { timeDifferenceForDate } from '../utils'
4-
import { Mutation } from 'react-apollo'
4+
import { useMutation } from 'urql'
55
import gql from 'graphql-tag'
66

77
const VOTE_MUTATION = gql`
@@ -23,45 +23,38 @@ const VOTE_MUTATION = gql`
2323
}
2424
`
2525

26-
class Link extends Component {
27-
render() {
28-
const authToken = localStorage.getItem(AUTH_TOKEN)
26+
const Link = ({ link, index }) => {
27+
const authToken = localStorage.getItem(AUTH_TOKEN);
28+
const [, executeMutation] = useMutation(VOTE_MUTATION);
2929

30-
return (
31-
<div className="flex mt2 items-start">
32-
<div className="flex items-center">
33-
<span className="gray">{this.props.index + 1}.</span>
34-
{authToken && (
35-
<Mutation
36-
mutation={VOTE_MUTATION}
37-
variables={{ linkId: this.props.link.id }}
38-
update={(store, { data: { vote } }) =>
39-
this.props.updateStoreAfterVote(store, vote, this.props.link.id)
40-
}
41-
>
42-
{voteMutation => (
43-
<div className="ml1 gray f11" onClick={voteMutation}>
44-
45-
</div>
46-
)}
47-
</Mutation>
48-
)}
49-
</div>
50-
<div className="ml1">
51-
<div>
52-
{this.props.link.description} ({this.props.link.url})
53-
</div>
54-
<div className="f6 lh-copy gray">
55-
{this.props.link.votes.length} votes | by{' '}
56-
{this.props.link.postedBy
57-
? this.props.link.postedBy.name
58-
: 'Unknown'}{' '}
59-
{timeDifferenceForDate(this.props.link.createdAt)}
30+
const voteMutation = React.useCallback(() => {
31+
executeMutation({ linkId: link.id })
32+
}, [link, executeMutation]);
33+
34+
return (
35+
<div className="flex mt2 items-start">
36+
<div className="flex items-center">
37+
<span className="gray">{index + 1}.</span>
38+
{authToken && (
39+
<div className="ml1 gray f11" onClick={voteMutation}>
40+
6041
</div>
42+
)}
43+
</div>
44+
<div className="ml1">
45+
<div>
46+
{link.description} ({link.url})
47+
</div>
48+
<div className="f6 lh-copy gray">
49+
{link.votes.length} votes | by{' '}
50+
{link.postedBy
51+
? link.postedBy.name
52+
: 'Unknown'}{' '}
53+
{timeDifferenceForDate(link.createdAt)}
6154
</div>
6255
</div>
63-
)
64-
}
56+
</div>
57+
)
6558
}
6659

6760
export default Link

0 commit comments

Comments
 (0)