【graphql】react調用graphql接口方法

前言

  • 上一篇寫了製作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大同小異,套路都是一個套路。
  • 展示組件那裏只要渲染出來即可自動刷新,就不放了。
  • 最後,需要代碼自取
發佈了153 篇原創文章 · 獲贊 8 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章