Skip to content
Toggle navigation
Projects
Groups
Snippets
Help
Toggle navigation
This project
Loading...
Sign in
hfpp2012
/
merng
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit 63d0cc84
authored
Nov 11, 2019
by
qiuzhi99
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
18_setContext
1 parent
723d4202
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
186 additions
and
30 deletions
client/package.json
client/src/ApolloProvider.js
client/src/App.js
client/src/components/MenuBar.js
client/src/components/PostForm.js
client/src/context/auth.js
client/src/pages/Home.js
client/src/pages/Login.js
client/src/utils/AuthRoute.js
client/yarn.lock
graphql/resolvers/posts.js
client/package.json
View file @
63d0cc8
...
...
@@ -6,9 +6,11 @@
"@apollo/react-hooks"
:
"^3.1.3"
,
"apollo-boost"
:
"^0.4.4"
,
"apollo-cache-inmemory"
:
"^1.6.3"
,
"apollo-link-context"
:
"^1.0.19"
,
"apollo-link-http"
:
"^1.5.16"
,
"graphql"
:
"^14.5.8"
,
"graphql-tag"
:
"^2.10.1"
,
"jwt-decode"
:
"^2.2.0"
,
"moment"
:
"^2.24.0"
,
"react"
:
"^16.10.2"
,
"react-dom"
:
"^16.10.2"
,
...
...
client/src/ApolloProvider.js
View file @
63d0cc8
...
...
@@ -4,11 +4,21 @@ import ApolloClient from "apollo-client";
import
{
ApolloProvider
}
from
"@apollo/react-hooks"
;
import
{
createHttpLink
}
from
"apollo-link-http"
;
import
{
InMemoryCache
}
from
"apollo-cache-inmemory"
;
import
{
setContext
}
from
"apollo-link-context"
;
const
httpLink
=
createHttpLink
({
uri
:
"http://localhost:5001"
});
const
authLink
=
setContext
(()
=>
{
const
token
=
localStorage
.
getItem
(
"jwtToken"
);
return
{
headers
:
{
Authorization
:
token
?
`Bearer
${
token
}
`
:
""
}
};
});
const
client
=
new
ApolloClient
({
link
:
httpLink
,
link
:
authLink
.
concat
(
httpLink
)
,
cache
:
new
InMemoryCache
()
});
...
...
client/src/App.js
View file @
63d0cc8
...
...
@@ -11,6 +11,7 @@ import MenuBar from "./components/MenuBar";
import
"./App.css"
;
import
{
AuthProvider
}
from
"./context/auth"
;
import
AuthRoute
from
"./utils/AuthRoute"
;
function
App
()
{
return
(
...
...
@@ -19,8 +20,8 @@ function App() {
<
Container
>
<
MenuBar
/>
<
Route
exact
path
=
"/"
component
=
{
Home
}
/
>
<
Route
exact
path
=
"/login"
component
=
{
Login
}
/
>
<
Route
exact
path
=
"/register"
component
=
{
Register
}
/
>
<
Auth
Route
exact
path
=
"/login"
component
=
{
Login
}
/
>
<
Auth
Route
exact
path
=
"/register"
component
=
{
Register
}
/
>
<
/Container
>
<
/Router
>
<
/AuthProvider
>
...
...
client/src/components/MenuBar.js
View file @
63d0cc8
import
React
,
{
useState
}
from
"react"
;
import
React
,
{
useState
,
useContext
}
from
"react"
;
import
{
Menu
}
from
"semantic-ui-react"
;
import
{
Link
}
from
"react-router-dom"
;
import
{
AuthContext
}
from
"../context/auth"
;
const
MenuBar
=
()
=>
{
const
{
user
,
logout
}
=
useContext
(
AuthContext
);
const
pathname
=
window
.
location
.
pathname
;
const
path
=
pathname
===
"/"
?
"home"
:
pathname
.
substr
(
1
);
const
[
activeItem
,
setActiveItem
]
=
useState
(
path
);
const
handleItemClick
=
(
e
,
{
name
})
=>
setActiveItem
(
name
);
return
(
<
div
>
<
Menu
size
=
"massive"
color
=
"teal"
pointing
secondary
>
const
menuBar
=
user
?
(
<
Menu
size
=
"massive"
color
=
"teal"
pointing
secondary
>
<
Menu
.
Item
name
=
{
user
.
username
}
active
as
=
{
Link
}
to
=
"/"
/>
<
Menu
.
Menu
position
=
"right"
>
<
Menu
.
Item
name
=
"logout"
onClick
=
{
logout
}
/
>
<
/Menu.Menu
>
<
/Menu
>
)
:
(
<
Menu
size
=
"massive"
color
=
"teal"
pointing
secondary
>
<
Menu
.
Item
name
=
"home"
active
=
{
activeItem
===
"home"
}
onClick
=
{
handleItemClick
}
as
=
{
Link
}
to
=
"/"
/>
<
Menu
.
Menu
position
=
"right"
>
<
Menu
.
Item
name
=
"
home
"
active
=
{
activeItem
===
"
home
"
}
name
=
"
login
"
active
=
{
activeItem
===
"
login
"
}
onClick
=
{
handleItemClick
}
as
=
{
Link
}
to
=
"/"
to
=
"/
login
"
/>
<
Menu
.
Menu
position
=
"right"
>
<
Menu
.
Item
name
=
"login"
active
=
{
activeItem
===
"login"
}
onClick
=
{
handleItemClick
}
as
=
{
Link
}
to
=
"/login"
/>
<
Menu
.
Item
name
=
"register"
active
=
{
activeItem
===
"register"
}
onClick
=
{
handleItemClick
}
as
=
{
Link
}
to
=
"/register"
/>
<
/Menu.Menu
>
<
/Menu
>
<
/div
>
<
Menu
.
Item
name
=
"register"
active
=
{
activeItem
===
"register"
}
onClick
=
{
handleItemClick
}
as
=
{
Link
}
to
=
"/register"
/>
<
/Menu.Menu
>
<
/Menu
>
);
return
menuBar
;
};
export
default
MenuBar
;
client/src/components/PostForm.js
0 → 100644
View file @
63d0cc8
import
React
from
"react"
;
import
{
Form
,
Button
}
from
"semantic-ui-react"
;
import
{
useForm
}
from
"../utils/hook"
;
import
{
useMutation
}
from
"@apollo/react-hooks"
;
import
gql
from
"graphql-tag"
;
function
PostForm
()
{
const
{
onChange
,
onSubmit
,
values
}
=
useForm
(
createPostCallback
,
{
body
:
""
});
const
[
createPost
,
{
error
}]
=
useMutation
(
CREATE_POST_MUTATION
,
{
update
(
_
,
result
)
{
values
.
body
=
""
;
},
variables
:
values
});
console
.
dir
(
error
);
function
createPostCallback
()
{
createPost
();
}
return
(
<>
<
Form
onSubmit
=
{
onSubmit
}
>
<
h2
>
Create
a
post
:
<
/h2
>
<
Form
.
Field
>
<
Form
.
Input
placeholder
=
"Hi World!"
value
=
{
values
.
body
}
name
=
"body"
error
=
{
error
?
true
:
false
}
onChange
=
{
onChange
}
/
>
<
Button
type
=
"submit"
color
=
"teal"
>
Submit
<
/Button
>
<
/Form.Field
>
<
/Form
>
{
error
&&
(
<
div
className
=
"ui error message"
style
=
{{
marginBottom
:
20
}}
>
<
ul
className
=
"list"
>
{
error
.
graphQLErrors
[
0
].
message
}
<
/ul
>
<
/div
>
)}
<
/
>
);
}
const
CREATE_POST_MUTATION
=
gql
`
mutation createPost($body: String!) {
createPost(body: $body) {
id
body
createdAt
username
likes {
id
username
createdAt
}
likeCount
comments {
id
body
username
createdAt
}
commentCount
}
}
`
;
export
default
PostForm
;
client/src/context/auth.js
View file @
63d0cc8
import
React
,
{
createContext
,
useReducer
}
from
"react"
;
import
jwtDecode
from
"jwt-decode"
;
const
initialState
=
{
user
:
null
};
if
(
localStorage
.
getItem
(
"jwtToken"
))
{
const
decodedToken
=
jwtDecode
(
localStorage
.
getItem
(
"jwtToken"
));
if
(
decodedToken
.
exp
*
1000
<
Date
.
now
())
{
localStorage
.
removeItem
(
"jwtToken"
);
}
else
{
initialState
.
user
=
decodedToken
;
}
}
const
AuthContext
=
createContext
({
user
:
null
,
...
...
@@ -25,9 +40,10 @@ function authReducer(state, action) {
}
function
AuthProvider
(
props
)
{
const
[
state
,
dispatch
]
=
useReducer
(
authReducer
,
{
user
:
null
}
);
const
[
state
,
dispatch
]
=
useReducer
(
authReducer
,
initialState
);
function
login
(
userData
)
{
localStorage
.
setItem
(
"jwtToken"
,
userData
.
token
);
dispatch
({
type
:
"LOGIN"
,
payload
:
userData
...
...
@@ -35,6 +51,7 @@ function AuthProvider(props) {
}
function
logout
()
{
localStorage
.
removeItem
(
"jwtToken"
);
dispatch
({
type
:
"LOGOUT"
});
...
...
client/src/pages/Home.js
View file @
63d0cc8
import
React
from
"react"
;
import
React
,
{
useContext
}
from
"react"
;
import
gql
from
"graphql-tag"
;
import
{
useQuery
}
from
"@apollo/react-hooks"
;
import
{
Grid
}
from
"semantic-ui-react"
;
import
PostCard
from
"../components/PostCard"
;
import
{
AuthContext
}
from
"../context/auth"
;
import
PostForm
from
"../components/PostForm"
;
const
FETCH_POSTS_QUERY
=
gql
`
{
...
...
@@ -27,6 +29,7 @@ const FETCH_POSTS_QUERY = gql`
`
;
const
Home
=
()
=>
{
const
{
user
}
=
useContext
(
AuthContext
);
const
{
loading
,
data
}
=
useQuery
(
FETCH_POSTS_QUERY
);
return
(
...
...
@@ -35,6 +38,11 @@ const Home = () => {
<
h1
>
Recent
Posts
<
/h1
>
<
/Grid.Row
>
<
Grid
.
Row
>
{
user
&&
(
<
Grid
.
Column
>
<
PostForm
/>
<
/Grid.Column
>
)}
{
loading
?
(
<
h1
>
Loading
posts
...
<
/h1
>
)
:
(
...
...
client/src/pages/Login.js
View file @
63d0cc8
...
...
@@ -21,6 +21,7 @@ const Login = props => {
data
:
{
login
:
userData
}
}
)
{
console
.
log
(
userData
);
context
.
login
(
userData
);
props
.
history
.
push
(
"/"
);
},
...
...
client/src/utils/AuthRoute.js
0 → 100644
View file @
63d0cc8
import
React
,
{
useContext
}
from
"react"
;
import
{
AuthContext
}
from
"../context/auth"
;
import
{
Route
,
Redirect
}
from
"react-router-dom"
;
function
AuthRoute
({
component
:
Compoment
,
...
rest
})
{
const
{
user
}
=
useContext
(
AuthContext
);
return
(
<
Route
{...
rest
}
render
=
{
props
=>
(
user
?
<
Redirect
to
=
"/"
/>
:
<
Compoment
{...
props
}
/>
)
}
/>
);
}
export
default
AuthRoute
;
client/yarn.lock
View file @
63d0cc8
...
...
@@ -1758,6 +1758,14 @@ apollo-client@^2.6.4:
tslib "^1.9.3"
zen-observable "^0.8.0"
apollo-link-context@^1.0.19:
version "1.0.19"
resolved "https://registry.npm.taobao.org/apollo-link-context/download/apollo-link-context-1.0.19.tgz#3c9ba5bf75ed5428567ce057b8837ef874a58987"
integrity sha1-PJulv3XtVChWfOBXuIN++HSliYc=
dependencies:
apollo-link "^1.2.13"
tslib "^1.9.3"
apollo-link-error@^1.0.3:
version "1.1.12"
resolved "https://registry.npm.taobao.org/apollo-link-error/download/apollo-link-error-1.1.12.tgz#e24487bb3c30af0654047611cda87038afbacbf9"
...
...
@@ -6011,6 +6019,11 @@ jsx-ast-utils@^2.1.0, jsx-ast-utils@^2.2.1:
array-includes "^3.0.3"
object.assign "^4.1.0"
jwt-decode@^2.2.0:
version "2.2.0"
resolved "https://registry.npm.taobao.org/jwt-decode/download/jwt-decode-2.2.0.tgz#7d86bd56679f58ce6a84704a657dd392bba81a79"
integrity sha1-fYa9VmefWM5qhHBKZX3TkruoGnk=
keyboard-key@^1.0.4:
version "1.0.4"
resolved "https://registry.npm.taobao.org/keyboard-key/download/keyboard-key-1.0.4.tgz#52d8fa07b7e17757072aa22a67fb4ae85e4c46b0"
...
...
graphql/resolvers/posts.js
View file @
63d0cc8
...
...
@@ -30,6 +30,10 @@ module.exports = {
async
createPost
(
_
,
{
body
},
context
)
{
const
user
=
checkAuth
(
context
);
if
(
body
.
trim
()
===
""
)
{
throw
new
Error
(
"Post body must not be empty"
);
}
const
newPost
=
new
Post
({
body
,
username
:
user
.
username
,
...
...
Write
Preview
Markdown
is supported
Attach a file
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to post a comment