CS174
Chris Pollett
Nov 30, 2022
mkdir graphql cd graphql npm init #go through prompts to make initial package.json file npm install nodemon #will use this to avoid having to restart server # when make changes to code npm install express --save npm install apollo-server-express --save
{
"name": "graphql",
"version": "1.0.0",
"description": "",
"main": "index.js",
"type": "module", //run as module
"scripts": {
"start": "node src/index.js", //run not in production mode
"dev": "nodemon src/index.js", //run in dev mode
//(slower, but don't need to restart on change)
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"apollo-server-express": "^3.11.1",
"express": "^4.18.2",
"nodemon": "^2.0.20"
}
}
import { ApolloServer, gql } from 'apollo-server-express';
import express from 'express';
const port = process.env.PORT || 8888;
/* typedefs are used by the gql module to specify the types for the field in
JSON return by a GraphQL query
*/
const typeDefs = gql`
type Query {
hello: String
}
`;
/*
resolvers are used to specify functions to handle filling in the values for
fields on a GraphQL query.
*/
const resolvers = {
Query : {
hello: () => 'Hello there!'
}
};
const app = express();
// Create and start Apollo Server
const server = new ApolloServer({typeDefs, resolvers});
await server.start()
server.applyMiddleware( {app, path: '/api'} );
// Get Express app to lister on port 8888
app.listen( {port }, () =>
console.log(`GraphQL Example on ${port}${server.graphqlPath}`));
npm run dev # if wanted to run production app code type npm run start
type Note {
id: ID!
content: String!
author: String!
}
type Query {
hello: String
notes: [Note!]! //idea is resolver for this field will return all notes
// the exclamation point inside the [] indicates that we must say which subfield we want
note (id: ID): Note! //idea is resolver for this
//field will return a particular note
}
import { ApolloServer, gql } from 'apollo-server-express';
import express from 'express';
const port = process.env.PORT || 8888;
let notes = [
{id: '1', content: 'First note', author: 'bob'},
{id: '2', content: 'Another note', author: 'sally'},
{id: '3', content: 'super note', author: 'alice'},
];
const typeDefs = gql`
type Note {
id: ID!
content: String!
author: String!
}
type Query {
hello: String
notes: [Note!]!
note(id: ID): Note!
}
type Mutation {
newNote(content: String!): Note!
}
`;
const resolvers = {
Query : { // these are the handlers for queries
hello: () => 'Hello there!',
notes: () => notes,
note: (parent, args) => {
return notes.find(note => note.id === args.id)
}
},
Mutation: {
newNote: (parent, args) => {
let noteValue = {
id: String(notes.length + 1),
content: args.content,
author: "Chris Pollett"
};
notes.push(noteValue);
return noteValue;
}
}
};
const app = express();
const server = new ApolloServer({typeDefs, resolvers});
await server.start()
server.applyMiddleware( {app, path: '/api'} );
app.listen( {port }, () =>
console.log(`GraphQL Example on ${port}${server.graphqlPath}`));

npx create-react-app react-test
cd react-test npm start
import logo from './logo.svg';
import './App.css';
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
export default App;
import './App.css';
function App() {
const name = 'Chris';
const now = String(new Date());
return (
<div className="App">
<p>Hello {name}!</p>
<p>The current time is {now}</p>
<p>I can also evaluate expressions such as 2+(3*5): {2+(3*5)}.</p>
</div>
);
}
export default App;
npm install @apollo/client graphql --save
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import { ApolloClient, ApolloProvider, InMemoryCache } from '@apollo/client'
const client = new ApolloClient({
uri: "http://localhost:8888/api",
cache: new InMemoryCache(),
})
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<ApolloProvider client={client}>
<App />
</ApolloProvider>
);
import { useQuery, gql } from "@apollo/client";
const GET_LISTS = gql`
query {
notes {
id
content
}
}
`;
function App() {
const { data, loading, error } = useQuery(GET_LISTS);
if (loading) return 'Loading...';
if (error) return `Error! ${error.message}`;
return (
<div>
{
data.results.map(item => {
return(
<div key={item.id} style={{display: 'flex', flexDirection: 'row'}}>
<h2>{item.id}. </h2>
<h2>{item.content}</h2>
</div>
)
})
}
</div>
)
}
export default App;
npm install --save react-router react-router-dom
import { BrowserRouter, Link, Route, Routes, useParams,}
from 'react-router-dom';
import React from 'react';
/* This page has multiple components on it we could
have split this across multiple files and imported them.
*/
/* This component shows react components can have forms.
It also shows a crude way to get the values off forms.
You could then send these values as a GraphQL query
*/
class Home extends React.Component
{
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(event) {
let user_name = document.getElementById('user-name').value;
alert(user_name);
event.preventDefault();
}
render() {
return (
<div className="app">
{/* We can enclosed a C comment in braces to make a JSX comment
*/}
<h1>Home Page Body</h1>
<form onSubmit={this.handleSubmit}>
<p><label for="user-name">User Name:</label>
<input id="user-name" type="text"/>
<button type="submit">Submit</button>
</p>
</form>
</div>
);
}
};
/* Here is a functional way to declare a component...
Notice a previously defined component can be used as
a tag in another component. This allows one to
have code that looks more like HTML rather than
have to call functions from your scripting language which
render elements.
*/
const AnotherHome = () => {
return (
<div className="app">
<h1>About Page</h1>
<p>Demoing we can use tags we have just defined...</p>
<Home />
</div>
);
};
/* We are going to use the number component below to
show how to bind url path variables to Javascript variables
*/
const Number = () => {
const { my_number1, my_number2 } = useParams();
return (
<div className="app">
<h1>MyNumber {my_number1} {my_number2}</h1>
</div>
);
};
// We'll render this component on failure to find a Route
const NotFound = () => {
return (
<div className="app">
<h1>Page not found</h1>
</div>
);
};
const App = () => (
<BrowserRouter>
<div>
{/*Notice how make links in React for routing */}
<Link to="/">Home</Link>{' '}
<Link to='/number/5/6'>Number-5-6</Link>{' '}
<Link to='/another_home'>Another Home</Link>{' '}
{/*React renders first route which matches */}
<Routes>
<Route exact path="/" element={<Home />} />
<Route path="/another_home" element={<AnotherHome />} />
{/*notice this route matches paths like /number/1/4 */}
<Route path="/number/:my_number1/:my_number2" element={<Number />} />
{/*notice the wildcard in this route */}
<Route path="/*" element={<NotFound />} />
</Routes>
</div>
</BrowserRouter>
);
export default App;