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 = (
    <ApolloProvider client={client}>
        <App />
    </ApolloProvider>
);

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 (
            <div>
                <Post/>
            </div>
        );
    }
}

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(
            <div>
                <div>
                    {
                        // loading状况时将显现...
                        getPostsDataLoading ? 
                            <div>...</div> 
                            : 
                            (
                                getPostsDataError ? 
                                    // 有毛病数据,将会显现毛病
                                    <div>{JSON.stringify(getPostsDataError)}</div> 
                                    : 
                                    // 一般则显现要求到的数据
                                    <div>{JSON.stringify(getPostsData.posts)}</div>
                            ) 
                    }
                </div >

                <hr />

                <div>
                    <input 
                        type="text" 
                        name="postId" 
                        value={postId} 
                        onChange={(e) => { 
                            this.setState({ postId: e.target.value }) 
                        }} 
                    /> 

                    <button onClick={() => {
                        // client 也是props传过来的对象,能够让我们主动提议要求
                        client.query({
                            // 对应定义的 getPost 查询
                            query: postQuery.getPost,
                            // 设置要求参数
                            variables: {
                                id: postId
                            }
                        }).then(({ data: { post } }) => {
                            this.setState({
                                post
                            })
                        })

                    }}>
                        getPost
                    </button>

                    <div>{JSON.stringify(post)}</div>
                </div>

                <hr/>

                <div>
                    <input 
                        type="text" 
                        value={newPost.title}
                        onChange={(e) => this.setState({ 
                            newPost: { 
                                ...newPost, 
                                title: e.target.value,
                            } 
                        })}
                    />

                    <input 
                        type="text" 
                        value={newPost.content}
                        onChange={(e) => this.setState({ 
                            newPost: { 
                                ...newPost, 
                                content: e.target.value,
                            } 
                        })}
                    />
                    
                    <button onClick={() => createPost({
                        // createPost是ApolloConsumer传过来的包装好的要求要领,
                        // 这里只用设置要求参数,loading,data,error 将会经由过程props
                        // 通报进来
                        variables: {
                            data: newPost
                        }
                    })}>
                        createPost
                    </button>

                    {
                        createPostLoading ?
                            <div>...</div> 
                            : 
                            <div>
                            {JSON.stringify(createPostData && createPostData.createPost)}
                            </div>
                    }
                </div>
            </div >
            
        )
    }
}

class PostWrap extends Component {
    render() {
        return (
            <ApolloConsumer>
            {(client) => (
                // 传入要运用的motation查询
                <Mutation mutation={postQuery.createPost}>
                    {(
                        // 要领重定名
                        createPost, 
                        { 
                            // 状况数据重定名
                            data: createPostData, 
                            loading: createPostLoading 
                        }
                    ) => (
                       // 当同时多个查询时,运用这类嵌套形式
                        <Query
                            query={postQuery.getPosts}
                            >
                                {({ 
                                    // 状况数据重定名
                                    data: getPostsData, 
                                    loading: getPostsLoading, 
                                    error: getPostsDataError 
                                }) => 
                                    // 将重定名的状况数据和查询要领通报到组件中
                                    // Query指定的查询在组件加载后就会自动提议要求
                                    <Post {...{
                                            client, 
                                            getPostsData, 
                                            getPostsLoading, 
                                            getPostsDataError, 
                                            createPost, 
                                            createPostData, 
                                            createPostLoading
                                        }} 
                                    />}
                        </Query>
                    )}
                </Mutation>
            )}
            </ApolloConsumer>
        )
    }
}

export default PostWrap;

经由过程这类体式格局我们能够在react中运用graphql了,这类体式格局极大方便了我们对要求数据api的治理,而且能够经由过程整合查询,削减页面的要求次数。
假如你对这系列文章有疑问或发现有毛病的处所,迎接在下方留言议论。

    原文作者:一番
    原文地址: https://segmentfault.com/a/1190000017224995
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞