Commit 63d0cc84 by qiuzhi99

18_setContext

1 parent 723d4202
......@@ -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",
......
......@@ -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()
});
......
......@@ -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} />
<AuthRoute exact path="/login" component={Login} />
<AuthRoute exact path="/register" component={Register} />
</Container>
</Router>
</AuthProvider>
......
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>
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"
......@@ -36,8 +44,9 @@ const MenuBar = () => {
/>
</Menu.Menu>
</Menu>
</div>
);
return menuBar;
};
export default MenuBar;
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;
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"
});
......
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>
) : (
......
......@@ -21,6 +21,7 @@ const Login = props => {
data: { login: userData }
}
) {
console.log(userData);
context.login(userData);
props.history.push("/");
},
......
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;
......@@ -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"
......
......@@ -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,
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!