使用Redux来结合GraphQL的方法

我在客户端使用了Redux、Redux-Saga,服务器端使用了Node.js(使用Koa框架和Sequelize ORM),并结合GraphQL。

使用的npm库围绕Graphql的部分

客户

react-apollo 反应阿波罗
graphql-tag 图形标签
apollo-client v2 阿波罗客户端 v2
apollo-link-http 阿波罗链接 HTTP
apollo-cache-redux 阿波罗缓存 Redux

服务器 (Sā fú qì)

阿波罗服务器扩展库apollo-server-koa
合并GraphQL模式的工具库merge-graphql-schemas

关于apollo-client v2

Apollo Client在版本1时可以与Redux一起使用,但在最新的版本2中取消了该支持。因此,在Apollo Client v2中需要与apollo-cache-redux一起使用。

以下是关于该问题的讨论:
https://github.com/apollographql/apollo-client/issues/2593
https://github.com/apollographql/apollo-client/issues/2509

当使用GraphQL和Redux进行搜索时,会找到一些日语资料。但是由于这些资料是基于apollo-client v1进行实现的,所以在使用v2时可能会遇到一些问题。

代码 (daima)

只需要一个选择,以下是对”graphql周围的部分”的中国翻译:
只保留有关GraphQL的部分并发布

服务器端的实现

const { typeDefs, resolvers } = require('./graphql');

const app = new Koa();

const server = new ApolloServer({
  typeDefs,
  resolvers,
});

server.applyMiddleware({ app }); // これで/graphqlというエンドポイントが用意される。
const path = require('path');
const { fileLoader, mergeTypes, mergeResolvers } = require('merge-graphql-schemas');

const typeDefs = mergeTypes(fileLoader(path.join(__dirname, './schema')));
const resolvers = mergeResolvers(fileLoader(path.join(__dirname, './resolvers')));

module.exports = {
  typeDefs,
  resolvers,
};

const db = require('models');

module.exports = {
  Query: {
    allAccount: () => db.accounts.findAll(), // sequelizeメソッド
  },
};
const { gql } = require('apollo-server-koa');

const typeDefs = gql`
  type Account {
    id: ID!
    last_name: String
    first_name: String
    email: String
  }

  type Query {
    allAccount: [Account]
  }
`;

module.exports = typeDefs;

在这个schema中定义了graphql的模式,resolver中将每个graphql查询与相应的函数(使用sequelize从数据库中获取数据的函数)关联起来。

现在,您可以使用以下的GraphQL查询。

  query {
    allAccount {
      id
      last_name
      first_name
      email
    }
  }

客户端的实现

import { ApolloClient } from 'apollo-client';
import { ReduxCache } from 'apollo-cache-redux';
import { HttpLink } from 'apollo-link-http';
import gql from 'graphql-tag';
import store from './store'; // reduxのstore

const cache = new ReduxCache({ store });
const httpLink = new HttpLink({
  uri: 'http://localhost:5000/graphql',
});

const client = new ApolloClient({
  link: httpLink,
  cache
});

export default client;

import { combineReducers } from 'redux';
import ui from './ui';
import { apolloReducer } from 'apollo-cache-redux';

const reducer = combineReducers({
  ui,
  apollo: apolloReducer
});

export default reducer;
import { ApolloProvider } from 'react-apollo';
import client from './client';
import store from './store';
import Routes from './routes';

const history = createBrowserHistory();

const render = () => {
  ReactDOM.render(
    <AppContainer>
      <ApolloProvider client={client}>
        <Provider store={store}>
          <Router history={history}>
            <Routes />
          </Router>
        </Provider>
      </ApolloProvider>
    </AppContainer>,
    document.getElementById('app')
  );
};
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { Query } from 'react-apollo';
import gql from 'graphql-tag';

const GET_ALL_ACCOUNT = gql`
  query {
    allAccount {
      id
      last_name
      first_name
      email
    }
  }
`;

const AccountContainerWithGql = () => (
  <Query query={GET_ALL_ACCOUNT}>
    {({ data, loading }) => {
      const { allAccount } = data;

      if (loading || !allAccount) {
        return <div>Loading</div>;
      }

      return <AccountContainer allAccount={allAccount} />;
    }}
  </Query>
);

class Account extends Component {
  render() {
    const accounts = this.props.allAccount;

    return (
      // 取ってきたアカウントのデータを使ってあとは好きにコンポーネントを作成
      <div>...</div>
    );
  }
}

const AccountContainer = connect()(Account);

export default AccountContainerWithGql;

这是将redux容器用react-apollo的Query包装起来的想法。

通过使用react-apollo提供的loading功能,可以轻松地在数据加载中显示加载消息。
此外,无需查看服务器端,就能在客户端上查看和编辑查询,这非常方便,并且不再需要准备用于数据获取的redux动作,这也非常方便。

如果使用apollo-client,则不需要redux吗?

专栏:GraphQL是否能取代Redux

我想指出的是,当引入Apollo Client到技术栈时,可能完全不需要Redux。Apollo客户端用于远程数据,但在React的本地状态下已足够管理本地数据。只有在本地数据状态变得复杂时,才需要引入像Redux这样精细的状态管理解决方案。

通过在应用程序中使用像Apollo Client这样的GraphQL库,可以解决许多痛点,但由于它负责管理远程数据的所有状态,因此在Redux或MobX这样的状态管理库应该放置在哪里可能会感到困惑。然而,您可以只在本地数据中使用Redux或MobX,并将远程数据保留在Apollo中,以便轻松处理。您不需要使用Redux的异步操作来获取数据。因此,Redux将成为应用程序的其余状态(例如本地数据/视图数据/UI数据等)的可预测状态容器。也许,Redux可能不再需要。

我还只写了一点点,但确实使用Query和Mutation时,数据的获取和更新都是在apollo-client中进行处理的,所以对于与界面相关的状态(如模态框的打开和关闭状态),似乎只有redux会拥有?
就redux-saga而言,由于与数据库相关的异步处理是在apollo-client中进行的,所以似乎完全不需要使用它。

bannerAds