如何使用 react-apollo graphql 确定突变加载状态
How to determine mutation loading state with react-apollo graphql
2018 更新: Apollo Client 2.1 添加了一个新的 Mutation 组件,该组件添加了加载 属性。请参阅下面的 @robin-wieruch 的回答和此处的公告 https://dev-blog.apollodata.com/introducing-react-apollo-2-1-c837cc23d926 请继续阅读原始问题,该问题现在仅适用于早期版本的 Apollo。
在 react-apollo
(v0.5.2), I don't see a documented way to inform my UI that a mutation is awaiting server response. I can see that earlier versions of the package 中使用当前版本的 graphql
高阶组件将发送 属性 指示加载。
查询仍然收到加载 属性,如此处记录:http://dev.apollodata.com/react/queries.html#default-result-props
我的应用程序也在使用 redux,所以我认为一种方法是将我的组件连接到 redux 并传递一个函数 属性,这将使我的 UI 进入加载状态.然后,当将我的 graphql 突变重写为 属性 时,我可以调用更新 redux 存储。
大致是这样的:
function Form({ handleSubmit, loading, handleChange, value }) {
return (
<form onSubmit={handleSubmit}>
<input
name="something"
value={value}
onChange={handleChange}
disabled={loading}
/>
<button type="submit" disabled={loading}>
{loading ? 'Loading...' : 'Submit'}
</button>
</form>
);
}
const withSubmit = graphql(
gql`
mutation submit($something : String) {
submit(something : $something) {
id
something
}
}
`,
{
props: ({ ownProps, mutate }) => ({
async handleSubmit() {
ownProps.setLoading(true);
try {
const result = await mutate();
} catch (err) {
// @todo handle error here
}
ownProps.setLoading(false);
},
}),
}
);
const withLoading = connect(
(state) => ({ loading: state.loading }),
(dispatch) => ({
setLoading(loading) {
dispatch(loadingAction(loading));
},
})
);
export default withLoading(withSubmit(Form));
我很好奇是否有更惯用的方法来通知 UI 突变是 "in-flight." 谢谢。
我有 re-posted this question on github and the suggested solution was to use something like a react higher order component just as you proposed in your original question. I did a similar thing – without using redux though – as outlined in this gist.
引用 Tom Coleman 对 github 问题的回应:
It doesn't really make sense to include loading state on the mutation
container; if you think about it you could call the mutation twice
simultaneously -- which loading state should get passed down to the child? My
feeling is in general it's not nice to mix imperative (this.mutate(x, y, z))
with declarative (props) things; it leads to irresolvable inconsistencies.
任何偶然发现这个问题的人,因为 Apollo Client 2.1 you have access to those properties in the Query and Mutation component's render props function。
import React from "react";
import { Mutation } from "react-apollo";
import gql from "graphql-tag";
const TOGGLE_TODO = gql`
mutation ToggleTodo($id: Int!) {
toggleTodo(id: $id) {
id
completed
}
}
`;
const Todo = ({ id, text }) => (
<Mutation mutation={TOGGLE_TODO} variables={{ id }}>
{(toggleTodo, { loading, error, data }) => (
<div>
<p onClick={toggleTodo}>
{text}
</p>
{loading && <p>Loading...</p>}
{error && <p>Error :( Please try again</p>}
</div>
)}
</Mutation>
);
注意:示例代码取自 Apollo Client 2.1 发布博客 post。
2018 更新: Apollo Client 2.1 添加了一个新的 Mutation 组件,该组件添加了加载 属性。请参阅下面的 @robin-wieruch 的回答和此处的公告 https://dev-blog.apollodata.com/introducing-react-apollo-2-1-c837cc23d926 请继续阅读原始问题,该问题现在仅适用于早期版本的 Apollo。
在 react-apollo
(v0.5.2), I don't see a documented way to inform my UI that a mutation is awaiting server response. I can see that earlier versions of the package 中使用当前版本的 graphql
高阶组件将发送 属性 指示加载。
查询仍然收到加载 属性,如此处记录:http://dev.apollodata.com/react/queries.html#default-result-props
我的应用程序也在使用 redux,所以我认为一种方法是将我的组件连接到 redux 并传递一个函数 属性,这将使我的 UI 进入加载状态.然后,当将我的 graphql 突变重写为 属性 时,我可以调用更新 redux 存储。
大致是这样的:
function Form({ handleSubmit, loading, handleChange, value }) {
return (
<form onSubmit={handleSubmit}>
<input
name="something"
value={value}
onChange={handleChange}
disabled={loading}
/>
<button type="submit" disabled={loading}>
{loading ? 'Loading...' : 'Submit'}
</button>
</form>
);
}
const withSubmit = graphql(
gql`
mutation submit($something : String) {
submit(something : $something) {
id
something
}
}
`,
{
props: ({ ownProps, mutate }) => ({
async handleSubmit() {
ownProps.setLoading(true);
try {
const result = await mutate();
} catch (err) {
// @todo handle error here
}
ownProps.setLoading(false);
},
}),
}
);
const withLoading = connect(
(state) => ({ loading: state.loading }),
(dispatch) => ({
setLoading(loading) {
dispatch(loadingAction(loading));
},
})
);
export default withLoading(withSubmit(Form));
我很好奇是否有更惯用的方法来通知 UI 突变是 "in-flight." 谢谢。
我有 re-posted this question on github and the suggested solution was to use something like a react higher order component just as you proposed in your original question. I did a similar thing – without using redux though – as outlined in this gist.
引用 Tom Coleman 对 github 问题的回应:
It doesn't really make sense to include loading state on the mutation container; if you think about it you could call the mutation twice simultaneously -- which loading state should get passed down to the child? My feeling is in general it's not nice to mix imperative (this.mutate(x, y, z)) with declarative (props) things; it leads to irresolvable inconsistencies.
任何偶然发现这个问题的人,因为 Apollo Client 2.1 you have access to those properties in the Query and Mutation component's render props function。
import React from "react";
import { Mutation } from "react-apollo";
import gql from "graphql-tag";
const TOGGLE_TODO = gql`
mutation ToggleTodo($id: Int!) {
toggleTodo(id: $id) {
id
completed
}
}
`;
const Todo = ({ id, text }) => (
<Mutation mutation={TOGGLE_TODO} variables={{ id }}>
{(toggleTodo, { loading, error, data }) => (
<div>
<p onClick={toggleTodo}>
{text}
</p>
{loading && <p>Loading...</p>}
{error && <p>Error :( Please try again</p>}
</div>
)}
</Mutation>
);
注意:示例代码取自 Apollo Client 2.1 发布博客 post。