Dad*_*les 7 javascript apollo reactjs react-native react-apollo
我们正在使用 Apollo Client 构建一个离线的第一个 React Native 应用程序。目前我正在尝试在离线时直接更新 Apollo Cache 以乐观地更新 UI。由于我们离线,我们不会尝试在连接为“在线”之前触发突变,但希望 UI 在仍处于离线状态时触发突变之前反映这些更改。我们正在使用来自http://dev.apollodata.com/core/read-and-write.html#writequery-and-writefragment的 readQuery / writeQuery API 函数。并且能够通过 Reacotron 查看正在更新的缓存,但是,UI 不会更新此缓存更新的结果。
const newItemQuantity = existingItemQty + 1;
const data = this.props.client.readQuery({ query: getCart, variables: { referenceNumber: this.props.activeCartId } });
data.cart.items[itemIndex].quantity = newItemQuantity;
this.props.client.writeQuery({ query: getCart, data });
Run Code Online (Sandbox Code Playgroud)
Seb*_*ber 13
如果您查看文档示例,您将看到它们以不可变的方式使用数据。传递给写入查询的数据属性与读取的对象不同。Apollo 不太可能支持改变这个对象,因为如果不进行深度复制和前后数据的比较,它检测你修改了哪些属性的效率不会很高。
const query = gql`
query MyTodoAppQuery {
todos {
id
text
completed
}
}
`;
const data = client.readQuery({ query });
const myNewTodo = {
id: '6',
text: 'Start using Apollo Client.',
completed: false,
};
client.writeQuery({
query,
data: {
todos: [...data.todos, myNewTodo],
},
});
Run Code Online (Sandbox Code Playgroud)
所以你应该在不改变数据的情况下尝试相同的代码。您可以使用如set
的lodash/fp
来帮助你
const data = client.readQuery({...});
const newData = set("cart.items["+itemIndex+"].quantity",newItemQuantity,data);
this.props.client.writeQuery({ ..., data: newData });
Run Code Online (Sandbox Code Playgroud)
它推荐ImmerJS进行更复杂的突变
只是为了节省某人的时间。以不可变的方式使用数据是解决方案。完全同意这个答案,但对我来说,我做错了其他事情,将在这里展示。我遵循了本教程, 并在完成本教程后更新缓存工作正常。因此,我尝试将这些知识应用到我自己的应用程序中,但即使我按照教程中所示进行了所有操作,更新也不起作用。
这是我使用状态更新数据以在渲染方法中访问数据的方法:
// ... imports
export const GET_POSTS = gql`
query getPosts {
posts {
id
title
}
}
`
class PostList extends Component {
constructor(props) {
super(props)
this.state = {
posts: props.posts
}
}
render() {
const postItems = this.state.posts.map(item => <PostItem key={item.id} post={item} />)
return (
<div className="post-list">
{postItems}
</div>
)
}
}
const PostListQuery = () => {
return (
<Query query={GET_POSTS}>
{({ loading, error, data }) => {
if (loading) {
return (<div>Loading...</div>)
}
if (error) {
console.error(error)
}
return (<PostList posts={data.posts} />)
}}
</Query>
)
}
export default PostListQuery
Run Code Online (Sandbox Code Playgroud)
解决方案只是直接访问日期,而根本不使用状态。看这里:
class PostList extends Component {
render() {
// use posts directly here in render to make `cache.writeQuery` work. Don't set it via state
const { posts } = this.props
const postItems = posts.map(item => <PostItem key={item.id} post={item} />)
return (
<div className="post-list">
{postItems}
</div>
)
}
}
Run Code Online (Sandbox Code Playgroud)
为了完整起见,这里是我用来添加新帖子和更新缓存的输入:
import React, { useState, useRef } from 'react'
import gql from 'graphql-tag'
import { Mutation } from 'react-apollo'
import { GET_POSTS } from './PostList'
const ADD_POST = gql`
mutation ($post: String!) {
insert_posts(objects:{title: $post}) {
affected_rows
returning {
id
title
}
}
}
`
const PostInput = () => {
const input = useRef(null)
const [postInput, setPostInput] = useState('')
const updateCache = (cache, {data}) => {
// Fetch the posts from the cache
const existingPosts = cache.readQuery({
query: GET_POSTS
})
// Add the new post to the cache
const newPost = data.insert_posts.returning[0]
// Use writeQuery to update the cache and update ui
cache.writeQuery({
query: GET_POSTS,
data: {
posts: [
newPost, ...existingPosts.posts
]
}
})
}
const resetInput = () => {
setPostInput('')
input.current.focus()
}
return (
<Mutation mutation={ADD_POST} update={updateCache} onCompleted={resetInput}>
{(addPost, { loading, data }) => {
return (
<form onSubmit={(e) => {
e.preventDefault()
addPost({variables: { post: postInput }})
}}>
<input
value={postInput}
placeholder="Enter a new post"
disabled={loading}
ref={input}
onChange={e => (setPostInput(e.target.value))}
/>
</form>
)
}}
</Mutation>
)
}
export default PostInput
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
7658 次 |
最近记录: |