紧接上篇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的治理,而且能够经由过程整合查询,削减页面的要求次数。
假如你对这系列文章有疑问或发现有毛病的处所,迎接在下方留言议论。