使用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中进行的,所以似乎完全不需要使用它。