如果我在我的应用程序中使用redux和apollo客户端,那么从组件外部的操作触发查询的最佳方法是什么.
例如,如果我有一个标准应用程序,配置了redux和apollo客户端,我应该如何触发"刷新"列表.我可以在具有gql的组件本身上触发一个函数,但是如何从一个更符合flux的动作中做到这一点.
import React, { Component, PropTypes } from 'react';
import { graphql } from 'react-apollo';
import gql from 'graphql-tag';
import { connect } from 'react-redux';
import { refreshProfile } from './actions';
class Profile extends Component { ... }
Profile.propTypes = {
data: PropTypes.shape({
loading: PropTypes.bool.isRequired,
user: PropTypes.object,
}).isRequired,
};
const UserQuery = gql`
query getUser {
user {
id
name
}
}
`;
const ProfileWithData = graphql(UserQuery)(Profile);
const ProfileWithDataAndState = connect(
(state) => ({ user: state.user })),
)(ProfileWithData);
Run Code Online (Sandbox Code Playgroud)
并且,说我想触发一个动作来刷新用户数据?由于逻辑在组件本身,我不知道如何从动作本身触发gql查询.
我有一个在创建或更新时触发的upsert查询.在更新时,Apollo将结果集成到缓存中,但在创建时却没有.
这是查询:
export const UPSERT_NOTE_MUTATION = gql`
mutation upsertNote($id: ID, $body: String) {
upsertNote(id: $id, body: $body) {
id
body
}
}`
Run Code Online (Sandbox Code Playgroud)
我的客户:
const graphqlClient = new ApolloClient({
networkInterface,
reduxRootSelector: 'apiStore',
dataIdFromObject: ({ id }) => id
});
Run Code Online (Sandbox Code Playgroud)
来自服务器的响应是相同的:返回两者id并body返回,但Apollo不会data自动将新ID添加到缓存对象中.
是否有可能让Apollo自动添加新对象而data不会触发后续获取?
这是我的数据存储的样子:
UPDATE
根据文档,该函数updateQueries应该允许我将新元素推送到我的资产列表,而不必再次触发我的原始获取查询.
该函数被执行但该函数返回的任何内容都被完全忽略,并且不修改缓存.
即使我做这样的事情:
updateQueries: {
getUserAssets: (previousQueryResult, { mutationResult }) => {
return {};
}
}
Run Code Online (Sandbox Code Playgroud)
没有什么变化.
更新#2
仍然无法获取我的资产列表进行更新.
在里面updateQueries,这是我的previousQueryResult样子:
updateQueries: {
getUserAssets: (previousQueryResult, …Run Code Online (Sandbox Code Playgroud) javascript react-redux apollostack react-apollo apollo-client
我有一个Article在我的架构中调用的类型:
type Article {
id: ID!
updated: DateTime
headline: String
subline: String
}
Run Code Online (Sandbox Code Playgroud)
对于它的更新,有一个updateArticle(id: ID!, article: ArticleInput!)突变使用的相应输入类型:
input ArticleInput {
headline: String
subline: String
}
Run Code Online (Sandbox Code Playgroud)
突变本身看起来像这样:
mutation updateArticle($id: ID!, $article: ArticleInput!) {
updateArticle(id: $id, article: $article) {
id
updated
headline
subline
}
}
Run Code Online (Sandbox Code Playgroud)
文章始终保存为一个整体(而不是单个字段逐个),所以当我通过了一篇文章,该突变我以前牵强,它会抛出这样的错误Unknown field. In field "updated",Unknown field. In field "__typename"和Unknown field. In field "id".这些有根本原因,那些字段没有在输入类型上定义.
根据规范,这是正确的行为:
(...)此无序映射不应包含任何名称未由此输入对象类型的字段定义的条目,否则应抛出错误.
现在我的问题是处理这些场景的好方法是什么.我应该将应用代码中输入类型允许的属性列入白名单吗?
如果可能的话我想避免这种情况,并且可能有一个实用程序功能将它们切换为我,它知道输入类型.但是,由于客户端不了解架构,因此必须在服务器端进行.因此,不必要的属性将转移到那里,我想这是他们不应该首先转移的原因.
有没有比白名单更好的方法?
我正在使用apollo-client,react-apollo而且graphql-server-express.
refetch重新访问数据供电的页面时如何获取新数据react-apollo?
说,我第一次访问列表页面.apollo将获取查询并默认缓存它.因此,当您在会话期间再次访问同一页面时,它将从其缓存存储中填充数据.apollo每次组件安装时如何强制重新获取数据?
(这是对https://github.com/apollographql/apollo-client/issues/1886的跟进)
我正在尝试构建一个文本输入,它将在用户输入时更新值.
我首先尝试使用optimisticResponse更新本地缓存作为用户类型.这是有效的,除了它会在每次击键时触发突变.除了通过请求充斥网络之外,还存在网络不一致的问题.最后一个突变可能首先到达,第一个突变最后到达.这导致服务器以过时值结束.以下是此竞争条件的示例:
type: a
mutate request: a
type: b
mutate request: ab
arrives on server: ab
arrives on server: a
Run Code Online (Sandbox Code Playgroud)
现在服务器在graphql中记录了"a",这是不正确的.
为了缓解这个问题,我对按键事件进行了辩论.虽然这确实有助于上述竞争条件,但它并没有解决它.如果网络比你的去抖阈值慢,那么仍有可能出现竞争条件.
因为我们现在正在对文本输入进行去抖动,所以我们需要向该React组件引入一个本地状态,以便在用户输入时立即更新(如github问题中建议的@jbaxleyiii).现在我们的状态位于两个位置(组件状态和apollo缓存).
这个问题的一个大问题是组件在收到新道具时不会更新.例如.当graphql更新并推送到客户端时.
因为debounce实际上并没有解决竞争条件,所以我添加了一个网络队列(除了去抖动),它将管理变异请求,以确保一次只有一个变异.如果在飞行中有一个突变请求时它会收到突变请求,它会将它排队等待第一个返回时被触发.如果已经有一个排队的突变,它将丢弃它并将其替换为新的突变(一次只能有一个项目在队列中).这是一个例子:
type: a
send mutate request: a
type: b
queues mutate request: ab << wait to send this until "a" comes back
type: c
replaces queued request: abc << discard the queued request for "ab", it's old now
response from server: a
send mutate request: abc …Run Code Online (Sandbox Code Playgroud) 在react-apollo 2.0.1中,我有一个如下所示的graphql类型:
type PagedThing {
data: [Thing]
total: Int
}
Run Code Online (Sandbox Code Playgroud)
在执行以下writeFragment时
client.writeFragment({
id,
fragment: gql`
fragment my_thing on Thing {
status
}
`,
data: {
status
}
})
Run Code Online (Sandbox Code Playgroud)
缓存未更新,新数据未显示在UI上.还有什么需要做的吗?
PS:为了安全起见,我使用了片段匹配
编辑1:
我收到错误:
无法匹配片段,因为缺少__typename属性:{"status":"online"}
所以我将代码更改为:
client.writeFragment({
id,
fragment: gql`
fragment my_thing on Thing {
status
}
`,
data: {
__typename: 'Thing',
status
}
})
Run Code Online (Sandbox Code Playgroud)
并且不会抛出任何错误,但更新仍然不会发生
我正在尝试在react-apollo应用程序中注销后重置商店.
所以我创建了一个名为"logout"的方法,当我点击一个按钮(并通过'onDisconnect'道具传递)时调用该方法.
要做到这一点,我试图遵循这个例子:https: //www.apollographql.com/docs/react/recipes/authentication.html
但在我的情况下,我希望LayoutComponent为HOC(并且它没有graphQL查询).
这是我的组件:
import React, {Component} from 'react';
import { withApollo, graphql } from 'react-apollo';
import { ApolloClient } from 'apollo-client';
import AppBar from 'material-ui/AppBar';
import Sidebar from 'Sidebar/Sidebar';
import RightMenu from 'RightMenu/RightMenu';
class Layout extends Component {
constructor(props) {
super(props);
}
logout = () => {
client.resetStore();
alert("YOUHOU");
}
render() {
return (
<div>
<AppBar title="myApp" iconElementRight={<RightMenu onDisconnect={ this.logout() } />} />
</div>
);
}
}
export default withApollo(Layout);
Run Code Online (Sandbox Code Playgroud)
这里的问题是"客户端"没有定义,我无法正常注销.您是否有任何想法帮助我处理这种情况或从apollo客户端注销的示例/最佳实践?
谢谢你提前
我正在使用apollo 2.0。我首先authUser graphql调用服务器以提供给定的用户名和密码,这会生成jwt令牌并作为响应返回令牌。我确实看到成功登录后将User其存储cache为id键值。我有Buy按钮,我需要做validateSSOSession的给予token。对于validateSSOSession,我需要token从缓存中读取。
我经历了client.readQuery,client.fragementQuery但是两者都不适用于我的情况bcz client.readQuery期望在服务器之前调用过相同的查询,并且我应该具有相同的变量。由于我没有,username/password所以我不能打电话client.readQuery。同样,client.fragementQuery期望id是强制性的。由于我没有,id因此无法使用它。
暂时,我只是data从下面cache进行迭代和过滤User。
const data = client.cache.data.data;
const users = _.values(data).filter(obj=>(obj.__typename==='User' && obj.token));
const token = users[0].token;
// Make graphql call to validate sso
const { data } = await client.query({
query: GET_SSO_USER,
variables: { token …Run Code Online (Sandbox Code Playgroud) 只是一个基本的apollo查询请求
this.client.query({
query: gql`
{
User(okta: $okta){
id
}
}`
}).then(result => {
this.setState({userid: result.data.User});
console.log(this.state.userid.id)
}).catch(error => {
this.setState({error: <Alert color="danger">Error</Alert>});
});
Run Code Online (Sandbox Code Playgroud)
问题是,如何/在何处设置$ okta变量.
没有在Stackoverflow或Google上找到解决方案 - 如果有人可以帮助我会很棒:)
我有一个称为React的组件HandleQuery,可以处理Apollo GraphQL查询的结果:
import React, { ReactNode } from 'react';
import { CenteredMessage } from './centered-message';
export interface HandleQueryProps {
loading: boolean,
error?: Error,
children: ReactNode
}
export const HandleQuery = ({ loading, error, children }: HandleQueryProps) => {
if (loading) {
return <CenteredMessage>Loading...</CenteredMessage>;
}
if (error) {
return <CenteredMessage>{error.message}</CenteredMessage>;
}
return children;
};
Run Code Online (Sandbox Code Playgroud)
当此组件在另一个组件中使用时,不会编译:
import React from 'react';
import { useQuery } from 'react-apollo-hooks';
import gql from 'graphql-tag';
import { HandleQuery } from '..';
import { MutationType } …Run Code Online (Sandbox Code Playgroud) react-apollo ×10
graphql ×6
apollo ×5
reactjs ×4
javascript ×2
apollostack ×1
caching ×1
graphql-js ×1
react-redux ×1
typescript ×1