React和Apollo结合前后端通信总结

  • react官方文档:https://react.docschina.org

  • Apollo官方文档:https://www.apollographql.com/docs/react

  • antd官方文档:https://ant.design/index-cn

  • MATERIAL-UI:https://material-ui.com/zh

    环境准备

  • 使用create-react-app脚手架创建react项目

    1
    create-react-app app
  • 安装对于Apollo和graphql的依赖

    1
    npm install @apollo/client graphql
  • 安装支持Apollo上传文件的依赖 https://github.com/jaydenseric/apollo-upload-client

    1
    npm install apollo-upload-client
  • 配置ApolloClient

    App.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    import { ApolloClient, ApolloProvider, InMemoryCache } from "@apollo/client";
    import { Route, BrowserRouter as Router } from "react-router-dom";
    import { createUploadLink } from "apollo-upload-client";
    const client = new ApolloClient({
    link: createUploadLink({
    uri: "http://xxxxxxxx/graphql/",
    }),
    cache: new InMemoryCache(),
    });
    function App() {
    return (
    <Router>
    <Header />
    <ApolloProvider client={client}>
    <Route path="/" component={} exact></Route>
    <Route path="/afp" component={} exact></Route>
    </ApolloProvider>
    </Router>
    );
    }
    export default App;

    以上完成了react和Apollo的结合,并支持上传文件的操作,在路由中的组件均可使用Apollo提供的方法进行请求和发送数据。

    使用Apollo进行数据交互

    以下内容均建立在函数组件的基础上。
    useQuery

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    import { gql, useQuery } from '@apollo/client';
    const GET_ALL_PRODUCTS = gql`
    query {
    products {
    id
    name
    appType
    }
    }
    `;
    const Index = () => {
    const { loading, error,data } = useQuery(GET_ALL_PRODUCTS);
    if (data)
    return (
    <div>
    {data.products.map((item) => {
    return (
    <li>{item.name}</li>
    );
    })}
    </div>
    );
    return null;
    };
    export default Index;

    当该组件渲染时,会自动的执行useQuery方法并将请求得到的数据赋值给data。在html的部分可以用data渲染UI。
    useLazyQuery

    1
    2
    3
    import { useLazyQuery } from "@apollo/client";
    import { GET_JSON_RESULT } from "../graphql/queries";
    const [getJSON, { data }] = useLazyQuery(GET_JSON_RESULT)

    使用该方法,可以返回一个函数(如上面的getJSON,方法名自己取的(下同))和一个对象。你可以在一些事件中按需要去执行查询(比如,点击按钮执行查询)。只需要在事件中调用返回的函数即可(如上面的getJSON)。但是,调用函数并不返回一个promise,所以你不能通过.then()得到返回的数据。个人推测执行查询是一个异步操作,如果此时,你打印data,得到的数据会是undefined,当查询结束后data才是查询得到的结果。那么如何能够拿到返回的数据并进行处理呢?
    可以使用如下方式:

    1
    2
    3
    4
    5
    6
    const [getJSON, { data }] = useLazyQuery(GET_JSON_RESULT, {
    onCompleted: (data) => {
    // onCompleted是内置回调,
    //形参data即为后台的响应内容,可以在此处进行处理。
    },
    });

    useMutation

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    import { gql,useMutation} from "@apollo/client";
    const CREATE_CHECKOUT = gql`
    mutation(
    $product: Int!
    $drawValue: String
    $inputValue: String
    $attr: [String]
    $file: Upload
    ) {
    CheckoutCreate(
    checkout: {
    product: $product
    drawValue: $drawValue
    inputValue: $inputValue
    attr: $attr
    uploadFile: $file
    }
    ) {
    ok
    token
    }
    }
    `;
    const [submitCheckout] = useMutation(CREATE_CHECKOUT);
    const submit=()=>{
    submitCheckout({
    variables: { product: 2,... },//传入变量
    }).then((res)=>{
    console.log(res)
    })
    return (
    <button onClick={()=>{submit()}}>submit</button>
    )
    }

    使用useMutation返回一个方法(如上面的submitCheckout),可以在事件中调用,比如点击按钮提交订单信息,同时返回一个promise,因此我们可以通过.then()的方式拿到后台的数据。
    以上三个方法能够完成获取和提交数据了,如果需要更加详细的教程:
    Query: https://www.apollographql.com/docs/react/data/queries/
    Mutation: https://www.apollographql.com/docs/react/data/mutations/

    Apollo缓存

    Apollo带有缓存机制,同一个请求,如果之前已经缓存了则不会发起请求,而是从缓存中取数据。所以,在轮询查询订单状态的时候应该设置以下缓存规则,即不使用缓存。如下:

    1
    2
    3
    const [getJSON, { data }] = useLazyQuery(GET_JSON_RESULT, {
    fetchPolicy: "no-cache",
    })

    文档地址:https://www.apollographql.com/docs/react/data/queries/#supported-fetch-policies