React
数据查询语言
GraphQL
代码示例:
// helloworld.js
const express = require('express')
const {buildSchema} = require('graphql')
const {graphqlHTTP} = require('express-graphql')
const app = express()
// 轮廓
const Schema = buildSchema(`
type Query {
hello: String
}
`)
const root = { // 处理器
hello: () => {
// 模拟数据库查询
return 'Hello World!'
}
}
app.use('/home', (req, res) => {
res.send('home data')
})
app.use('/list', (req, res) => {
res.send('list data')
})
app.use('/graphql', graphqlHTTP({
schema: Schema,
rootValue: root,
graphiql: true // 开启查询器
}))
app.listen(3000)
/*
query {
hello
}
*/
参数类型与传递
代码示例:
// helloworld.js
const express = require('express')
const {buildSchema} = require('graphql')
const {graphqlHTTP} = require('express-graphql')
const app = express()
const Schema = buildSchema(`
type Account {
name: String,
age: Int,
location: String
}
type Film {
id: Int,
name: String,
price: Int
}
type Query {
getAllNames: [String],
getAccountInfo: Account,
getNowplayingList: [Film],
getFilmDetail(id: Int!):Film
}
`)
// !:必须传的参数
const fakeDB = [
{
id: 1,
name: 'Foo',
price: 1024
}
]
const root = {
getAllNames: () => {
return ['aaa', 'bbb', 'ccc']
},
getAccountInfo: () => {
// 模拟数据库
return {
name: 'Bar',
age: 24,
location: '幻想乡'
}
},
getNowplayingList() {
return fakeDB
},
getFilmDetail({id}) {
// console.log(obj, id)
return fakeDB.filter(item => item.id === id)[0] // 因为返回的并不是一个纯数组
}
}
app.use('/graphql', graphqlHTTP({
schema: Schema,
rootValue: root,
graphiql: true
}))
app.listen(3000)
/*
query {
getAllNames,
getAccountInfo {
name
},
getNowplayingList {
id,
name
},
getFilmDetail(id: 1) {
id
}
}
*/
mutation
代码示例:
// helloworld.js
const express = require('express')
const {buildSchema} = require('graphql')
const {graphqlHTTP} = require('express-graphql')
const app = express()
const Schema = buildSchema(`
type Film {
id: Int,
name: String,
price: Int
}
input FilmInput {
name: String,
price: Int
}
type Query {
getNowplayingList: [Film],
},
type Mutation {
createFilm(input: FilmInput): Film,
updateFilm(id: Int, input: FilmInput): Film,
deleteFilm(id: Int!): Int
}
`)
let fakeDB = [
{
id: 1,
name: 'Foo',
price: 1024
}
]
const root = {
getNowplayingList() {
return fakeDB
},
createFilm({input}) { // 模拟
const obj = {...input, id: fakeDB.length + 1}
fakeDB.push(obj)
return obj
},
updateFilm({id, input}) {
// console.log(id, input)
let current = null
fakeDB = fakeDB.map(item => {
if (item.id === id) {
current = {...item, ...input}
return {...item, ...input}
}
return item
})
return current
},
deleteFilm({id}) {
fakeDB = fakeDB.filter(item => item.id !== id)
return 1
}
}
app.use('/graphql', graphqlHTTP({
schema: Schema,
rootValue: root,
graphiql: true
}))
app.listen(3000)
/*
# query {
# }
mutation {
# createFilm(input: {
# name: "Bar",
# price: 2048
# }) {
# id,
# name,
# price
# }
# updateFilm(id: 1, input: {
# name: "HQSY"
# }) {
# id
# }
deleteFilm(id: 1)
}
*/
结合数据库
代码示例:
// db.js
const mongoose = require('mongoose')
mongoose.connect('mongodb://127.0.0.1:27017/test')
// helloworld.js
const express = require('express')
const {buildSchema} = require('graphql')
const {graphqlHTTP} = require('express-graphql')
require('./db')
const mongoose = require("mongoose");
const FilmModel = mongoose.model('film', new mongoose.Schema({
name: String,
price: Number
}))
const app = express()
const Schema = buildSchema(`
type Film {
id: String,
name: String,
price: Int
}
input FilmInput {
name: String,
price: Int
}
type Query {
getNowplayingList: [Film],
},
type Mutation {
createFilm(input: FilmInput): Film,
updateFilm(id: String, input: FilmInput): Film,
deleteFilm(id: String!): Int
}
`)
// id字段会自动转换_id
const root = {
getNowplayingList() {
return FilmModel.find()
},
createFilm({input}) {
return FilmModel.create({ // 本身返回值就是Promise对象
...input
})
},
updateFilm({id, input}) {
return FilmModel.updateOne({
_id: id
}, {
...input
}).then(res => FilmModel.find({_id: id})).then(res => res[0]) // 返回的对象跟之前不一样
},
deleteFilm({id}) {
return FilmModel.deleteOne({_id: id}).then(res => 1).catch(err => 0)
}
}
app.use('/graphql', graphqlHTTP({
schema: Schema,
rootValue: root,
graphiql: true
}))
app.listen(3000)
结合HTML
代码示例:
// helloworld.js
const express = require('express')
const {buildSchema} = require('graphql')
const {graphqlHTTP} = require('express-graphql')
require('./db')
const mongoose = require("mongoose");
const FilmModel = mongoose.model('film', new mongoose.Schema({
name: String,
price: Number
}))
const app = express()
const Schema = buildSchema(`
type Film {
id: String,
name: String,
price: Int
}
input FilmInput {
name: String,
price: Int
}
type Query {
getNowplayingList: [Film],
},
type Mutation {
createFilm(input: FilmInput): Film,
updateFilm(id: String, input: FilmInput): Film,
deleteFilm(id: String!): Int
}
`)
const root = {
getNowplayingList() {
return FilmModel.find()
},
createFilm({input}) {
return FilmModel.create({
...input
})
},
updateFilm({id, input}) {
return FilmModel.updateOne({
_id: id
}, {
...input
}).then(res => FilmModel.find({_id: id})).then(res => res[0])
},
deleteFilm({id}) {
return FilmModel.deleteOne({_id: id}).then(res => 1).catch(err => 0)
}
}
app.use('/graphql', graphqlHTTP({
schema: Schema,
rootValue: root,
graphiql: true
}))
app.use(express.static('public'))
app.listen(3000)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Home</title>
</head>
<body>
<button onclick="getData()">查询数据</button>
<button onclick="createData()">创建数据</button>
<button onclick="updateData()">更新数据</button>
<button onclick="deleteData()">删除数据</button>
<script>
function getData() {
const query = `
query {
getNowplayingList {
id,
name
}
}
`
fetch('/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({
query
})
}).then(res => res.json()).then(res => {
console.log(res)
})
}
function createData() {
const query = `
mutation($input: FilmInput) {
createFilm(input: $input) {
id,
name
}
}
`
fetch('/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({
query,
variables: { // 固定的字段
input: {
name: "Foo",
price: 1024,
}
}
})
}).then(res => res.json()).then(res => {
console.log(res)
})
}
function updateData() {
const query = `
mutation($id: String!, $input: FilmInput) {
updateFilm(id: $id, input: $input) {
id,
name
}
}
`
fetch('/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({
query,
variables: {
id: "6321a5a361e5cd6a24c16419",
input: {
name: "Bar",
price: 2048,
}
}
})
}).then(res => res.json()).then(res => {
console.log(res)
})
}
function deleteData() {
const query = `
mutation($id: String!) {
deleteFilm(id: $id)
}
`
fetch('/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({
query,
variables: {
id: "6321a5a361e5cd6a24c16419"
}
})
}).then(res => res.json()).then(res => {
console.log(res)
})
}
</script>
</body>
</html>
结合React
无参数
代码示例:
// src/setupProxy.js
const {createProxyMiddleware} = require('http-proxy-middleware')
module.exports = (app) => {
app.use(
'/graphql',
createProxyMiddleware({
target: 'http://localhost:3000',
changeOrigin: true
})
)
}
// src/App.jsx
import React from "react";
import {createRoot} from "react-dom/client";
import App from "./graphql/query";
createRoot(document.getElementById('root')).render(<App/>)
// src/graphql/query.jsx
import React from "react";
import {ApolloClient, InMemoryCache, ApolloProvider, gql, useQuery} from '@apollo/client';
const client = new ApolloClient({
uri: '/graphql',
cache: new InMemoryCache(),
});
function MyQuery() {
const GET_LOCATIONS = gql`
query {
getNowplayingList {
id,
name,
price
}
}
`
const {loading, data} = useQuery(GET_LOCATIONS);
// console.log(loading, error, data)
return (
<div>
{
!loading && data.getNowplayingList.map(item => <div key={item.id}>
<div>名字:{item.name}</div>
<div>价格:{item.price}</div>
</div>)
}
</div>
)
}
export default function App() {
return (
<ApolloProvider client={client}>
<MyQuery/>
</ApolloProvider>
)
}
有参数
代码示例:
// helloworld.js
const express = require('express')
const {buildSchema} = require('graphql')
const {graphqlHTTP} = require('express-graphql')
require('./db')
const mongoose = require("mongoose");
const FilmModel = mongoose.model('film', new mongoose.Schema({
name: String,
price: Number
}))
const app = express()
const Schema = buildSchema(`
type Film {
id: String,
name: String,
price: Int
}
input FilmInput {
name: String,
price: Int
}
type Query {
getNowplayingList(id: String!): [Film],
},
type Mutation {
createFilm(input: FilmInput): Film,
updateFilm(id: String!, input: FilmInput): Film,
deleteFilm(id: String!): Int
}
`)
const root = {
getNowplayingList({id}) {
return FilmModel.find({_id: id})
},
createFilm({input}) {
return FilmModel.create({
...input
})
},
updateFilm({id, input}) {
return FilmModel.updateOne({
_id: id,
}, {
...input
}).then(res => FilmModel.find({_id: id})).then(res => res[0])
},
deleteFilm({id}) {
return FilmModel.deleteOne({_id: id}).then(res => 1).catch(err => 0)
}
}
app.use('/graphql', graphqlHTTP({
schema: Schema,
rootValue: root,
graphiql: true
}))
app.use(express.static('public'))
app.listen(3000)
// src/graphql/query.jsx
import React, {useState} from "react";
import {ApolloClient, InMemoryCache, ApolloProvider, gql, useQuery} from '@apollo/client';
const client = new ApolloClient({
uri: '/graphql',
cache: new InMemoryCache(),
});
function MyQuery() {
const [state, setState] = useState({
id: "632187347260573c261b1a42"
})
const query = gql`
query getNowplayingList($id: String!) {
getNowplayingList(id: $id) {
id,
name,
price
}
}
`
const {loading, data} = useQuery(query, {
variables: {id: state.id}
});
// console.log(loading, error, data)
return (
<div>
<input type="text" onChange={evt => {
setState({
id: evt.target.value
})
}}/>
{
!loading && data.getNowplayingList.map(item => <div key={item.id}>
<div>名字:{item.name}</div>
<div>价格:{item.price}</div>
</div>)
}
</div>
)
}
export default function App() {
return (
<ApolloProvider client={client}>
<MyQuery/>
</ApolloProvider>
)
}
React-mutation
增
代码示例:
// src/graphql/query.jsx
import React from "react";
import {ApolloClient, InMemoryCache, ApolloProvider, gql, useMutation} from '@apollo/client';
const client = new ApolloClient({
uri: '/graphql',
cache: new InMemoryCache(),
});
function MyQuery() {
const query = gql`
mutation createFilm($input: FilmInput) {
createFilm(input: $input) {
id,
name,
price
}
}
`
const [createFilm] = useMutation(query, {
variables: {
input: {
name: "Foo",
price: 1024
}
}
})
// console.log(createFilm)
return (
<div>
<button onClick={() => {
createFilm().then(res => {
console.log(res)
}).catch(err => console.log(err))
}}>add</button>
</div>
)
}
export default function App() {
return (
<ApolloProvider client={client}>
<MyQuery/>
</ApolloProvider>
)
}
删
代码示例:
// src/graphql/query.jsx
import React from "react";
import {ApolloClient, InMemoryCache, ApolloProvider, gql, useMutation} from '@apollo/client';
const client = new ApolloClient({
uri: '/graphql',
cache: new InMemoryCache(),
});
function MyQuery() {
const query = gql`
mutation deleteFilm($id: String!) {
deleteFilm(id: $id)
}
`
const [deleteFilm] = useMutation(query, {
variables: {
id: "6321da8867b4e3a653f55129"
}
})
return (
<div>
<button onClick={() => {
deleteFilm().then(res => {
console.log(res)
}).catch(err => console.log(err))
}}>delete</button>
</div>
)
}
export default function App() {
return (
<ApolloProvider client={client}>
<MyQuery/>
</ApolloProvider>
)
}
改
代码示例:
// src/graphql/query.jsx
import React from "react";
import {ApolloClient, InMemoryCache, ApolloProvider, gql, useMutation} from '@apollo/client';
const client = new ApolloClient({
uri: '/graphql',
cache: new InMemoryCache(),
});
function MyQuery() {
const query = gql`
mutation updateFilm($id: String!, $input: FilmInput) {
updateFilm(id: $id, input: $input) {
id,
name,
price
}
}
`
const [updateFilm] = useMutation(query, {
variables: {
id: "6321da8867b4e3a653f55129",
input: {
name: "Foo",
price: 1024
}
}
})
return (
<div>
<button onClick={() => {
updateFilm().then(res => {
console.log(res)
}).catch(err => console.log(err))
}}>update</button>
</div>
)
}
export default function App() {
return (
<ApolloProvider client={client}>
<MyQuery/>
</ApolloProvider>
)
}