graphql redux

by Howon Song

通过宋颂恩

如何在Redux应用程序中使用GraphQL (How to use GraphQL in your Redux app)

Fetching and managing data in Redux requires too much work. As Sashko Stubailo points out:

在Redux中获取和管理数据需要太多的工作。 正如Sashko Stubailo 指出的那样 :

Unfortunately the patterns for asynchronously loading server data in a Redux app aren’t as well established, and often involve using external helper libraries, like redux-saga. You need to write custom code to call your server endpoints, interpret the data, normalize it, and insert it into the store — all while keeping track of various error and loading states.

不幸的是,在Redux应用程序中异步加载服务器数据的模式还不够完善,通常涉及使用外部帮助程序库,例如redux-saga 。 您需要编写自定义代码来调用服务器端点,解释数据,对其进行规范化并将其插入存储中,同时还要跟踪各种错误和加载状态。

By the end of this tutorial, you will have learned how to solve this problem by letting the Apollo Client fetch and manage data for you. You will no longer have to write multiple action dispatchers, reducers, and normalizers to fetch and sync data between your front end and your back end.

在本教程结束时,您将学习如何通过让Apollo Client为您获取和管理数据来解决此问题。 您将不再需要编写多个动作分派器,Reducer和Normalizer来在前端和后端之间获取和同步数据。

But before starting the tutorial, make sure that:

但是在开始本教程之前,请确保:

  • You know the basics of GraphQL queries — if you’re entirely new to GraphQL, you should come back after doing this tutorial.

    您知道GraphQL查询的基础知识—如果您是GraphQL的新手,那么应该在完成本教程后再回来。

  • You have some experience working with React/Redux — if not, you should come back after doing react tutorial and redux tutorial.

    您有使用React / Redux的经验-如果没有,您应该在完成react教程和redux教程之后再回来。

In this tutorial, we will go through 6 sections together.

在本教程中,我们将一起经历6个部分。

  1. Setting up server environment (quick)设置服务器环境(快速)
  2. Setting up redux boilerplate app设置Redux样板程序
  3. Adding GraphQL client (Apollo Client)添加GraphQL客户端(Apollo客户端)
  4. Fetching data with GraphQL query使用GraphQL查询获取数据
  5. Fetching even more data获取更多数据
  6. Next steps下一步

1.设置服务器环境 (1. Setting up server environment)

First, we need a GraphQL server. The easiest way to have a running server is completing this awesome tutorial.

首先,我们需要一个GraphQL服务器。 使服务器运行的最简单方法是完成本很棒的教程 。

If you are feeling lazy, you can just clone my repo, which is almost the same server you’d get if you did the tutorial yourself. The server supports GraphQL queries to fetch data from a SQLite DB.

如果您感到懒惰,则可以克隆我的repo ,这与您亲自完成本教程时所获得的服务器几乎相同。 该服务器支持GraphQL查询以从SQLite数据库获取数据。

Let’s run it and see if it’s working correctly:

让我们运行它,看看它是否正常工作:

$ git clone https://github.com/woniesong92/apollo-starter-kit$ cd apollo-starter-kit$ npm install$ npm start

The server should be running at http://localhost:8080/graphql. Navigate to that page and see if you get a working GraphiQL interface with results like this:

服务器应在http:// localhost:8080 / graphql上运行 。 导航至该页面,查看是否有一个可用的GraphiQL界面,其结果如下:

GraphiQL lets you test different queries and immediately see what response you get from the server. If we don’t want an author’s last name and a fortune cookie message in a response, we can update the query like below:

GraphiQL使您可以测试不同的查询,并立即查看从服务器获得的响应。 如果我们不希望在回复中使用作者的姓氏和幸运饼干消息,则可以如下更新查询:

And that’s exactly how we like it. We confirmed that our server is running fine and returning good responses, so let’s start building the client.

这正是我们喜欢的方式。 我们确认我们的服务器运行良好并且返回了良好的响应,因此让我们开始构建客户端。

2.设置redux样板程序 (2. Setting up redux boilerplate app)

For simplicity, we will use a redux boilerplate so we can get all the setup (e.g. Babel, webpack, CSS, etc.) for free. I like this boilerplate because its setup is easy to follow and is client-side only — which makes it perfect for this tutorial.

为简单起见,我们将使用redux样板文件,以便我们免费获得所有设置(例如Babel,webpack,CSS等)。 我喜欢这个样板,因为它的设置很容易遵循,并且仅在客户端使用-这使其非常适合本教程。

$ git clone https://github.com/woniesong92/react-redux-starter-kit.git$ cd react-redux-starter-kit$ npm install$ npm start

Let’s navigate to http://localhost:3000/ to see if the client server is running.

让我们导航到http:// localhost:3000 /以查看客户端服务器是否正在运行。

Yay! The client is running. It’s time for us to start adding a GraphQL client. Again, our goal is to easily fetch data from the server and render it in the landing page (HomeView) without much effort by using GraphQL queries.

好极了! 客户端正在运行。 是时候开始添加GraphQL客户端了。 同样,我们的目标是通过使用GraphQL查询轻松地从服务器获取数据并将其呈现在登录页面(HomeView)中。

3.添加GraphQL客户端(Apollo客户端) (3. Adding GraphQL client (Apollo Client))

Install the packages apollo-client, react-apollo, and graphql-tag.

安装软件包apollo-client,react-apollo和graphql-tag。

$ npm install apollo-client react-apollo graphql-tag --save

Then, open the file src/containers/AppContainer.js, the root of our Redux app. This is where we pass down the redux store to child components, using the Provider from react-redux.

然后,打开文件src / containers / AppContainer.js,这是我们的Redux应用程序的根目录。 这是我们使用react-redux的Provider将redux存储传递给子组件的地方。

import React, { PropTypes } from 'react'import { Router } from 'react-router'import { Provider } from 'react-redux'
class AppContainer extends React.Component {  static propTypes = {    history: PropTypes.object.isRequired,    routes: PropTypes.object.isRequired,    routerKey: PropTypes.number,    store: PropTypes.object.isRequired  }
render () {    const { history, routes, routerKey, store } = this.props
return (      <Provider store={store}>        <div>          <Router history={history} children={routes} key={routerKey} />        </div>      </Provider>    )  }}
export default AppContainer

We have to initialize an ApolloClient and replace the Provider from react-redux with ApolloProvider from react-apollo.

我们必须初始化ApolloClient并用react-apollo的ApolloProvider替换react-redux的Provider。

import React, { Component, PropTypes } from 'react'import { Router } from 'react-router'import ApolloClient, { createNetworkInterface, addTypename } from 'apollo-client'import { ApolloProvider } from 'react-apollo'
const client = new ApolloClient({  networkInterface: createNetworkInterface('http://localhost:8080/graphql'),  queryTransformer: addTypename,})
class AppContainer extends Component {  static propTypes = {    history: PropTypes.object.isRequired,    routes: PropTypes.object.isRequired,    store: PropTypes.object.isRequired  }
render () {    const { history, routes } = this.props
return (      <ApolloProvider client={client}>        <div>          <Router history={history} children={routes} />        </div>      </ApolloProvider>    )  }}
export default AppContainer

That’s it! We just added a GraphQL client to a plain Redux app that easily.

而已! 我们只是将GraphQL客户端轻松添加到普通的Redux应用程序中。

Let’s go ahead and try our first GraphQL query.

让我们继续尝试第一个GraphQL查询。

4.使用GraphQL查询获取数据 (4. Fetching data with GraphQL queries)

Open src/views/HomeView.js

打开src / views / HomeView.js

import React from 'react'import { connect } from 'react-redux'import { bindActionCreators } from 'redux'
export class HomeView extends React.Component {  constructor(props) {    super(props)  }
render () {    return (      <div className='home'>        <h1>Hello World</h1>      </div>    )  }}
// This is where you usually retrieve the data stored in the redux store (e.g posts: state.posts.data)const mapStateToProps = (state, { params }) => ({
})
// This is where you usually bind dispatch to actions that are used to request data from the backend. You will call the dispatcher in componentDidMount.const mapDispatchToProps = (dispatch) => {  const actions = {}
return {    actions: bindActionCreators(actions, dispatch)  }}
export default connect(  mapStateToProps,  mapDispatchToProps)(HomeView)

HomeView is a conventional Redux container (smart component). To use GraphQL queries instead of action dispatchers to fetch data, we will make some changes together.

HomeView是常规的Redux容器(智能组件)。 要使用GraphQL查询而不是动作分配器来获取数据,我们将一起进行一些更改。

  1. Remove mapDispatchToProps() and mapStateToProps() completely.完全删除mapDispatchToProps()和mapStateToProps()。
import React from 'react'import { connect } from 'react-redux'import { bindActionCreators } from 'redux'
export class HomeView extends React.Component {  constructor(props) {    super(props)  }
render () {    return (      <div className='home'>        <h1>Hello World</h1>      </div>    )  }}
export default connect({
})(HomeView)

2. Add mapQueriesToProps() and define a GraphQL query that will fetch the author information. Notice how this is the exactly the same query that we tested in the beginning using the GraphIQL interface on the server.

2.添加mapQueriesToProps()并定义一个GraphQL查询,以获取作者信息。 请注意,这与我们一开始使用服务器上的GraphIQL接口测试的查询完全相同。

import React from 'react'import { connect } from 'react-redux'import { bindActionCreators } from 'redux'
export class HomeView extends React.Component {  constructor(props) {    super(props)  }
render () {    return (      <div className='home'>        <h1>Hello World</h1>      </div>    )  }}
// NOTE: This will be automatically fired when the component is rendered, sending this exact GraphQL query to the backend.const mapQueriesToProps = ({ ownProps, state }) => {  return {    data: {      query: gql`        query {          author(firstName:"Edmond", lastName: "Jones"){            firstName            posts {              title            }          }        }      `    }  }}
export default connect({
})(HomeView)

3. Replace connect from react-redux with connect from react-apollo and pass mapQueriesToProps as argument. Once mapQueriesToProps is connected to ApolloClient, the query will automatically fetch the data from the backend when HomeView is rendered, and pass the data down through props.

3.将react-redux的connect替换为react-apollo的connect,并将mapQueriesToProps作为参数传递。 将mapQueriesToProps连接到ApolloClient后,呈现HomeView时,查询将自动从后端获取数据,并将数据向下传递到props。

import React from 'react'import { connect } from 'react-apollo' // NOTE: different connect!import gql from 'graphql-tag' // NOTE: lets us define GraphQL queries in a template language
export class HomeView extends React.Component {  constructor(props) {    super(props)  }
render () {    return (      <div className='home'>        <h1>Hello World</h1>      </div>    )  }}
const mapQueriesToProps = ({ ownProps, state }) => {  return {    data: {      query: gql`        query {          author(firstName:"Edmond", lastName: "Jones"){            firstName            posts {              title            }          }        }      `    }  }}
export default connect({  mapQueriesToProps})(HomeView)

4. Render the data that’s passed down from the props:

4.渲染从道具传下来的数据:

import React from 'react'import { connect } from 'react-apollo' // NOTE: different connect!import gql from 'graphql-tag' // NOTE: lets us define GraphQL queries in a template language
export class HomeView extends React.Component {  constructor(props) {    super(props)  }
render () {    const author = this.props.data.author    if (!author) {      return <h1>Loading</h1>    }
return (      <div>        <h1>{author.firstName}'s posts</h1>        {author.posts && author.posts.map((post, idx) => (          <li key={idx}>{post.title}</li>        ))}      </div>    )  }}
const mapQueriesToProps = ({ ownProps, state }) => {  return {    data: {      query: gql`        query {          author(firstName:"Edmond", lastName: "Jones"){            firstName            posts {              title            }          }        }      `    }  }}
export default connect({  mapQueriesToProps})(HomeView)

If all went well, your rendered HomeView should look like below:

如果一切顺利,则呈现的HomeView应该如下所示:

To fetch and render the data we wanted, we didn’t have to write any action dispatcher, reducer, or normalizer. All we had to do on the client was to write a single GraphQL query!

为了获取和呈现我们想要的数据,我们不必编写任何动作分派器,reducer或normalizer。 我们在客户端上要做的就是编写一个GraphQL查询!

We successfully achieved our initial goal. But that query was quite simple. What if we wanted to display all authors instead of just one author?

我们成功实现了最初的目标。 但是该查询非常简单。 如果我们想显示所有作者而不是一个作者怎么办?

5.获取更多数据 (5. Fetching even more data)

In order to fetch and display all authors, we have to update our GraphQL query and render method:

为了获取并显示所有作者,我们必须更新GraphQL查询和渲染方法:

import React from 'react'import { connect } from 'react-apollo' // NOTE: different connect!import gql from 'graphql-tag' // NOTE: lets us define GraphQL queries in a template language
export class HomeView extends React.Component {  constructor(props) {    super(props)  }
render () {    const authors = this.props.data.authors    if (!authors) {      return <h1>Loading</h1>    }
return (      <div>        {authors.map((author, idx) => (          <div key={'author-'+idx}>            <h1>{author.firstName}'s posts</h1>            {author.posts && author.posts.map((post, idx) => (              <li key={idx}>{post.title}</li>            ))}          </div>        ))}      </div>    )  }}
const mapQueriesToProps = ({ ownProps, state }) => {  return {    data: {      query: gql`        query {          authors {            firstName            posts {              title            }          }        }      `    }  }}
export default connect({  mapQueriesToProps})(HomeView)

However, once you refresh your browser HomeView page, you will notice that you have an error in your console:

但是,刷新浏览器的HomeView页面后,您会注意到控制台中出现错误:

ApolloError {graphQLErrors: Array[1], networkError: undefined, message: “GraphQL error: Cannot query field “authors” on type “Query”. Did you mean “author”?”}

ApolloError {graphQLErrors:Array [1],networkError:未定义,消息:“ GraphQL错误:无法查询类型为“ Query”的字段“ authors”。 您是说“作者”吗?”}

Ah, right! In our GraphQL server, we didn’t really define how to fetch authors.

啊,对! 在我们的GraphQL服务器中,我们并未真正定义如何获取作者

Let’s go back to our server and see what we have. Open the file apollo-starter-kit/data/resolvers.js

让我们回到服务器,看看有什么。 打开文件apollo-starter-kit / data / resolvers.js

import { Author, FortuneCookie } from './connectors';
const resolvers = {  Query: {    author(_, args) {      return Author.find({ where: args });    },    getFortuneCookie() {      return FortuneCookie.getOne()    }  },  Author: {    posts(author) {      return author.getPosts();    },  },  Post: {    author(post) {      return post.getAuthor();    },  },};
export default resolvers;

Looking at Query resolver, we notice that our GraphQL server only understands author and getFortuneCookie queries now. We should teach it how to “resolve” the query authors.

查看查询解析器时,我们注意到我们的GraphQL服务器现在仅了解authorgetFortuneCookie查询。 我们应该教它如何“解决”查询作者。

import { Author, FortuneCookie } from './connectors';
const resolvers = {  Query: {    author(_, args) {      return Author.find({ where: args });    },    getFortuneCookie() {      return FortuneCookie.getOne()    },    authors() { // the query "authors" means returning all authors!      return Author.findAll({})    }  },  ...};
export default resolvers;

We are not done yet. Open the file apollo-starter-kit/data/schema.js

我们还没有完成。 打开文件apollo-starter-kit / data / schema.js

const typeDefinitions = `...
type Query {  author(firstName: String, lastName: String): Author  getFortuneCookie: String}schema {  query: Query}`;
export default [typeDefinitions];

This Schema makes it clear what kind of queries the server should expect. It doesn’t expect authors query yet so let’s update it.

该模式使服务器可以清楚地查询哪种查询。 它不希望作者查询,所以让我们对其进行更新。

const typeDefinitions = `...
type Query {  author(firstName: String, lastName: String): Author  getFortuneCookie: String,  authors: [Author] // 'authors' query should return an array of                     // Author}schema {  query: Query}`;
export default [typeDefinitions];

Now that our GraphQL server knows what the “authors” query means, let’s go back to our client. We already updated our query so we don’t have to touch anything.

现在,我们的GraphQL服务器知道“作者”查询的含义了,让我们回到客户端。 我们已经更新了查询,因此我们无需触摸任何内容。

export class HomeView extends React.Component {
...
const mapQueriesToProps = ({ ownProps, state }) => {  return {    data: {      query: gql`        query {          authors {            firstName            posts {              title            }          }        }      `    }  }}
export default connect({  mapQueriesToProps})(HomeView)

With this query we expect to get all authors with their first names and posts. Go ahead and refresh the browser to see if we are getting the right data.

通过此查询,我们希望获得所有作者的名字和职位。 继续并刷新浏览器,看看我们是否获取了正确的数据。

If everything went well, your HomeView page will look like above.

如果一切顺利,您的HomeView页面将如上所示。

6.后续步骤 (6. Next steps)

This tutorial only explores a small part of GraphQL and leaves out a lot of concepts such as updating data on the server or using a different backend server (e.g. Rails).

本教程仅探讨GraphQL的一小部分,并省略了许多概念,例如更新服务器上的数据或使用其他后端服务器(例如Rails)。

While I work to introduce these in subsequent tutorials, you can read Sashko’s post or the Apollo Client Doc to better understand what’s going on under the hood (for example, what happened when we replaced Provider with ApolloProvider?).

当我在后续教程中介绍这些内容时,您可以阅读Sashko的帖子或Apollo Client Doc,以更好地了解幕后情况(例如,当我们用ApolloProvider替换Provider时发生了什么?)。

Digging into the source code of GitHunt, a full-stack Apollo Client and Server example app, also seems a great way to learn.

深入学习GitHunt的源代码(一个完整的Apollo客户端和服务器示例应用程序),也是一种学习的好方法。

If you have feedback, please leave it in the comment. I will try my best to be helpful :)

如果您有反馈,请留在评论中。 我会尽力为您提供帮助:)

翻译自: https://www.freecodecamp.org/news/tutorial-how-to-use-graphql-in-your-redux-app-9bf8ebbeb362/

graphql redux

graphql redux_如何在Redux应用程序中使用GraphQL相关推荐

  1. react 交互_如何在React应用程序中跟踪用户交互

    react 交互 by Faouzi Oudouh 通过Faouzi Oudouh 如何在React应用程序中跟踪用户交互 (How to track user interactions in you ...

  2. 如何在Web应用程序中使用TWAIN驱动程序的自定义功能?

    如何在Web应用程序中使用TWAIN驱动程序的自定义功能?接下来跟着小编一起来看看如何去实现. 本文适用于以下产品: Dynamic Web TWAIN v7 以上 ImageCapture Suit ...

  3. kotlin数据库_如何在Kotlin应用程序中使用Xodus数据库

    kotlin数据库 I want to show you how to use one of my favorite database choices for Kotlin applications. ...

  4. chrome麦克风权限_如何在Chrome扩展程序中处理麦克风输入权限和语音识别

    chrome麦克风权限 by Palash Taneja 由Palash Taneja 如何在Chrome扩展程序中处理麦克风输入权限和语音识别 (How to handle mic input pe ...

  5. Redux简介以及Redux应用程序中的状态更新方式

    by Syeda Aimen Batool 通过Syeda Aimen Batool Redux简介以及Redux应用程序中的状态更新方式 (An intro to Redux and how sta ...

  6. angular发布代码有缓存_如何在Angular应用程序中执行请求?

    全文共5358字,预计学习时长16分钟 来源:Pexels 本文将讨论如何在Angular应用程序中执行请求. 1. 使用拦截器来装饰请求 2. HttpClient 与HttpBackend的对比 ...

  7. 如何在 Java 应用程序中设置 HicariCP 连接池

    在本教程中,我们将介绍 HikariCP 并展示如何在 Java 应用程序中设置 HicariCP 连接池.在我们的应用程序中,我们向 MySQL 数据库发出请求. HikariCP是可靠的高性能 J ...

  8. java web 使用https_如何在Web应用程序中实现HTTPS登录页面?

    小编典典 首先,您需要为服务器启用SSL.对于Tomcat,您需要生成一个openSSL密钥库,并将以下连接器添加到server.xml: keystoreFile="mykeystore& ...

  9. java 登录 https_java – 如何在Web应用程序中实现HTTPS登录页面?

    首先,您需要为您的服务器启用SSL.对于Tomcat,您需要生成一个openSSL密钥库,并将以下连接器添加到server.xml: keystoreFile="mykeystore&quo ...

最新文章

  1. MoviePy - 中文文档2-快速上手-MoviePy-预览
  2. 蚂蚁金服发布「定损宝」,推动图像定损技术在车险领域的应用
  3. 时间管理无非就是一个玩耍俄罗斯方块的过程,堆堆堆哈哈哈哈
  4. 面向对象之: 反射和双下方法
  5. matlab gui从模型里获取参数程序,matlab gui 中参数传递的问题
  6. kaggle实战_4解决高维数据分类/回归问题--房价预测
  7. Restricted Boltzmann Machine (RBM)限制波尔兹曼机
  8. securecrt遇到一个致命的错误且必须关闭_高性能服务器之路 | 浅谈 Valgrind 内存错误检查神器 Memcheck...
  9. gtest简短,简单易用
  10. ios icon尺寸问题
  11. HSF框架日常问题记录1
  12. 家用无线网络优化方案
  13. IBM_System_x3650服务器固件升级手顺
  14. 狼的故事17:大结局
  15. 用python,重温小时候猜数字大小游戏
  16. JavaScript广告代码大全
  17. 什么是冲突域,什么是广播域?区别又是什么
  18. 第三章,矩阵,06-初等变换与初等矩阵
  19. mac的键位说明——⌘、⌥、⇧、⌃、⎋代表哪个键
  20. DES加密之强制更新下载分离器

热门文章

  1. wiki多个文件一起导入_mac文件信息管理工具EagleFiler for Mac分享给大家
  2. OSS正式支持IPv6公测
  3. java常用的7大排序算法汇总
  4. 基于html5海贼王单页视差滚动特效
  5. [原]VS2012编译GLEW 1.11
  6. 编译安装linux内核步骤
  7. SCCM 2012 SP1系列(七)分发部署exe软件
  8. 时髦而精巧的Iphone墙纸收集
  9. Windows Phone 7 SDK 7.1 Beta2 发布
  10. 怎么样才能快速的把淘宝店铺推广出去