react+graphql起手和特性介绍(三)

紧接上篇react+graphql起手和特性介绍(二),介绍完graphql与koa的服务搭建和graphql的一些常用特性,接下来我们介绍下在react中如何使用graphql
我们使用create-react-app创建react应用:

npm i -g create-react-app
mkdir react-graphql-app
create-react-app react-graphql-app

安装以下前端依赖

npm install react-apollo graphql-tag graphql apollo-client apollo-cache-inmemory apollo-link-http

各个依赖包的作用:

  • apollo-link-http 请求配置和网络请求能力
  • apollo-cache-inmemory 数据缓存
  • apollo-client 请求流程控制,生成请求数据,错误控制,响应数据解析
  • graphql-tag 查询类的schema数据解析,包含对应的 webpack-loader
  • react-apollo 连接graphql与react
  • graphql 提供graphql的核心执行能力

然后我们进行react和graphql的整合

// src/index.js

import React from 'react';
import ReactDOM from 'react-dom';

import { ApolloClient } from 'apollo-client';
import { createHttpLink } from 'apollo-link-http';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { ApolloProvider } from 'react-apollo';

import App from './App';

// 我们可以自定义fetch,对请求进行统一处理
const customFetch = (uri, options) => {
    return fetch(uri, options);
};


const client = new ApolloClient({
    // 连接到graphql服务器
    link: createHttpLink({ uri: 'http://localhost:9191/graphql', fetch: customFetch }),
    // 设置缓存
    cache: new InMemoryCache(),
});

// ApolloProvider 为react提供graphql能力
const WrappedApp = (
    
        
    
);

ReactDOM.render(WrappedApp, document.getElementById('root'));

为了能解析.graphql文件,需要修改webpack配置,添加graphql-loader

// config/webpack.config.dev.js && config/webpack.config.prod.js

...

module.exports = {
    ...
    
    module: {
        strictExportPresence: true,
        rules: [
            ...
            
            {
                // 解析 .graphql/.gql 后缀的loader
                test: /\.(graphql|gql)$/,
                exclude: /node_modules/,
                loader: 'graphql-tag/loader',
            },
            
            ...
        ]
    }
    ...
}

我们以post为示例,讲一下在组件中要做什么操作
创建定义查询的schema文件

# src/post.graphql

# 导入 user.graphql
#import "./user.graphql"

# fragment 定义片段,可以用于多个地方
fragment PostInfo on Post {
    id
    title
    content
    userId
    user {
        ...UserInfo
    }
}

query getPost($id: ID!) {
    post(id: $id) {
        id
        title
        content
        userId
        user {
            id
            name
            age
            available
            birthday
            money
            gender
        }
    }
}

query getPosts {
    posts {
        ...PostInfo
    }
}


mutation createPost($data: PostInput!) {
    createPost(data: $data) {
        ...PostInfo
    }
}
# src/user.graphql

fragment UserInfo on User {
    id
    name
    age
    available
    birthday
    tags
    gender
    role
}
// src/App.js

import React, { Component } from 'react';
import Post from './Post';

class App extends Component {
    render() {
        return (
            
); } } export default App;
// src/Post.js

import React, { Component } from 'react';
import { Query, Mutation, ApolloConsumer } from "react-apollo";
// 导入查询定义,定义的查询名次对应导入对象的方法名称,如 getPost => postQuery.getPost
import postQuery from './post.graphql';

class Post extends Component {
    state = {
        post: {},
        postId: '',
        newPost: {
            title: '',
            content: '',
        }
    }

    render() {
        // 由ApolloConsumer传入我们需要的数据,包含:
        // data 正常返回时的数据
        // loading 正在请求时loading会为true
        // error 发生错误时error将会有错误数据
        // 这里进行了重命名,将创建post,获取posts列表进行了命名区分
        const { 
            client, 
            getPostsData, getPostsDataLoading,
            createPost, createPostData, createPostLoading, 
            getPostsDataError
        } = this.props;

        const { postId, post, newPost } = this.state;
        return(
            
{ // loading状态时将显示... getPostsDataLoading ?
...
: ( getPostsDataError ? // 有错误数据,将会显示错误
{JSON.stringify(getPostsDataError)}
: // 正常则显示请求到的数据
{JSON.stringify(getPostsData.posts)}
) }

{ this.setState({ postId: e.target.value }) }} />
{JSON.stringify(post)}

this.setState({ newPost: { ...newPost, title: e.target.value, } })} /> this.setState({ newPost: { ...newPost, content: e.target.value, } })} /> { createPostLoading ?
...
:
{JSON.stringify(createPostData && createPostData.createPost)}
}
) } } class PostWrap extends Component { render() { return ( {(client) => ( // 传入要使用的motation查询 {( // 方法重命名 createPost, { // 状态数据重命名 data: createPostData, loading: createPostLoading } ) => ( // 当同时多个查询时,使用这种嵌套模式 {({ // 状态数据重命名 data: getPostsData, loading: getPostsLoading, error: getPostsDataError }) => // 将重命名的状态数据和查询方法传递到组件中 // Query指定的查询在组件加载后就会自动发起请求 } )} )} ) } } export default PostWrap;

通过这种方式我们可以在react中使用graphql了,这种方式极大方便了我们对请求数据api的管理,而且可以通过整合查询,减少页面的请求次数。
如果你对这系列文章有疑问或发现有错误的地方,欢迎在下方留言讨论。

你可能感兴趣的:(javascript,graphql)