graphql redux_如何在Redux应用程序中使用GraphQL

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值