前言
- 上一篇寫了製作graphql接口,接口必須有前臺客戶端連接它實現增刪改查,這次使用react進行連接。記錄下實現方法。
流程
- 首先創建項目使用create-react-app。
- 還需要安裝:
cnpm install apollo-boost @apollo/react-hooks graphql --save
- 先在react的index.js裏測試下是否能跑通:
import React from 'react';
import ReactDOM from 'react-dom';
import ApolloClient, {gql} from 'apollo-boost'
const client=new ApolloClient ({
uri:'http://localhost:4000/graphql'
})
client.query({
query:gql`
query{
getCategories{
id,name
}
}
`
}).then(result=>console.log(result))
- 控制檯如果打印出結果說明ok。
- 也就是說,如果要發請求,直接使用client.query發就行了。但是很多組件都會用到,直接傳肯定不方便,所以使用上下文傳遞:
import React from 'react';
import ReactDOM from 'react-dom';
import ApolloClient, {gql} from 'apollo-boost'
import {ApolloProvider} from '@apollo/react-hooks'
import App from './App'
const client=new ApolloClient ({
uri:'http://localhost:4000/graphql'
})
ReactDOM.render(
<ApolloProvider client = {client}>
<App></App>
</ApolloProvider>,document.getElementById('root')
)
- 下面就是如何在組件裏查詢graphql,爲了有點樣式,我引入了antd。
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import ApolloClient from 'apollo-boost'
import {ApolloProvider} from '@apollo/react-hooks'
import App from './App'
import 'antd/dist/antd.css';
const client=new ApolloClient ({
uri:'http://localhost:4000/graphql'
})
ReactDOM.render(
<ApolloProvider client = {client}>
<App></App>
</ApolloProvider>,document.getElementById('root')
)
App.js
import React from 'react';
import { Layout, Menu, Breadcrumb } from 'antd';
import MyContent from './mycontent'
const {Footer,Header,Content} = Layout
export default function (){
return (
<Layout className="layout">
<Header>
<div className="logo" />
<Menu
theme="dark"
mode="horizontal"
defaultSelectedKeys={['2']}
style={{ lineHeight: '64px' }}
>
<Menu.Item key="1">nav 1</Menu.Item>
<Menu.Item key="2">nav 2</Menu.Item>
<Menu.Item key="3">nav 3</Menu.Item>
</Menu>
</Header>
<Content style={{ padding: '0 50px' }}>
<Breadcrumb style={{ margin: '16px 0' }}>
<Breadcrumb.Item>Home</Breadcrumb.Item>
<Breadcrumb.Item>List</Breadcrumb.Item>
<Breadcrumb.Item>App</Breadcrumb.Item>
</Breadcrumb>
<div style={{ background: '#fff', padding: 24, minHeight: 280 }}> <MyContent></MyContent></div>
</Content>
<Footer style={{ textAlign: 'center' }}>Ant Design ©2018 Created by Ant UED</Footer>
</Layout>
)
}
- 我們做一個左邊進行增刪改查,右邊展示的功能。
- 最後樣式是這樣:
- 當時刪除和增加寫的是需要用id刪除的接口,所以這裏就靠id,也可以改成別的,但需要改接口。
- 我們需要把查詢語句統一做在一個文件裏:
query.js
import {gql} from 'apollo-boost'
export const CATEGORIES_PRODUCT=gql`
query{
getCategories {
id,
name,
products{
id,
name,
}
}
getProducts {
id
name,
category{
id,
name,
products{
id,
name,
}
}
}
}`
export const CATEGORIES = gql`
query{
getCategories {
id
name
}
}
`;
export const PRODUCTS = gql`
query{
getProducts {
id
name,
category{
id,
name
}
}
}`;
export const ADD_PRODUCT = gql`
mutation($name:String!,$category: String!){
addProduct(name: $name,category:$category) {
id,
name,
category{
id,
name
}
}
}`;
export const ADD_CATEGORY = gql`
mutation($name:String!){
addCategory(name:$name) {
id,
name
}
}`;
export const DEL_PRODUCT = gql`
mutation ($name:String!,$categoryId: String!){
delProductByName(name: $name, category: $categoryId) {
id
name
category {
id
name
products {
id
name
}
}
}
}
`
- 這個帶變量的寫法都是固定寫法,詳情可以參照阿波羅react鉤子官網。
- 這個使用的時候會靠usequery或者usemutation鉤子,生成一個方法,利用方法去查詢:
//使用語句修改
const [addcategory]=useMutation(ADD_CATEGORY)
addcategory({variables:values,refetchQueries:[{query:CATEGORIES_PRODUCT}]})
//使用語句查詢
const {data}=useQuery(CATEGORIES_PRODUCT);
- 這個variables就是對象裏那個變量了,注意這個變量名要和查詢語句變量名對上。
- 特別說一下這個refetchQueries,這個屬性就可以做完操作之後緊接着去做個查詢。乍看之下好像沒啥特別的,但是依賴這個查詢結果的變量會自動刷新,不用自己寫useState,useEffect這些,非常方便。這感覺就好像是查詢的這些變量都在一個store裏,你mutation改完後,調個更新,然後依賴這數據生成的結構也會自動刷新。
mycontent.js
import React from 'react'
import { useQuery } from '@apollo/react-hooks';
import {CATEGORIES_PRODUCT} from './query';
import ChangeProduct from './content/changeproduct'
import DisplayProduct from './content/displayproduct'
export default function(){
const {data}=useQuery(CATEGORIES_PRODUCT);
return (<div style={{display:"flex"}}>
<ChangeProduct ></ChangeProduct>
<DisplayProduct getProducts = {data}> </DisplayProduct>
</div>)
}
changeproduct.js
import React from 'react'
import Addcategory from './addcategory';
import Addproduct from './addproduct';
import Deleteproduct from './deleteproduct'
function ChangeProduct(props) {
return (
<div style={{flex:'1'}} >
<Addproduct></Addproduct>
<Addcategory></Addcategory>
<Deleteproduct></Deleteproduct>
</div>
)
}
export default ChangeProduct
addcategory.js
import React from 'react'
import { Form, Input, Button } from 'antd';
import { useMutation } from '@apollo/react-hooks';
import { CATEGORIES_PRODUCT,ADD_CATEGORY} from '../query';
function AddCategory(props){
const formItemLayout ={
labelCol: { span: 4 },
wrapperCol: { span: 14 },
}
const buttonItemLayout ={
wrapperCol: { span: 14, offset: 4 },
}
const { getFieldDecorator } = props.form;
const [addcategory]=useMutation(ADD_CATEGORY)
function categorySubmit(e){
e.preventDefault();
props.form.validateFields((err, values) => {
if (!err) {
console.log('Received values of form: ', values);
addcategory({variables:values,refetchQueries:[{query:CATEGORIES_PRODUCT}]})
}
});
}
return (
<Form layout="horizontal" onSubmit={categorySubmit}>
<Form.Item label="ADD Category" {...formItemLayout}>
</Form.Item>
<Form.Item label="CATEGORY" {...formItemLayout}>
{getFieldDecorator('name', {
rules: [{ required: true, message: 'input category' }],
})(
<Input placeholder="input category"/>,
)}
</Form.Item>
<Form.Item {...buttonItemLayout}>
<Button type="primary" htmlType="submit" className="login-form-button">submit</Button>
</Form.Item>
</Form>
)
}
const WrappedForm = Form.create({})(AddCategory);
export default WrappedForm
- 其他修改跟addcategory大同小異,套路都是一個套路。
- 展示組件那裏只要渲染出來即可自動刷新,就不放了。
- 最後,需要代碼自取。