How to get updated data from apollo cache

2019-05-07 15:49发布

问题:

Does Apollo client have some sort of thing like mapStateToProps (Redux)?

let's say I have a component, after query I know there's data in the cache so I do something like:

    class Container extends React.Component {
      ...
      ...
      render() {
        const notes = this.props.client.readFragment(NOTES_FRAGMENT)
        // notes has everything I need
        return (<Child notes={notes} />);
      }

    }
    export default WithApollo(Container);

However when I have a sibling component which calls mutation and do update, the <Child /> component's props never get updates.

class AnotherContainer extends React.Component {
   render() {
     return(
       <Mutation
          mutation={UPDATE_NOTE}
          update={(cache, {data: {updateNote}}) =? {
            const list = cache.readFragment({
              fragment: NOTES_FRAGMENT
            })
            // manipulate list
            cache.writeFragment({fragment:NOTES_FRAGMENT, data })
          }
        }
     )
   }
}

so my question is, how do I update the <Child /> component's props whenever I do writeFragment? is there anything like mapStateToProps thing to "connect" the notes props to the cache, so whenever it updates, will trigger the React lifecycle?

回答1:

react-apollo provides three ways you can listen for changes in the cache: 1) the Query component, 2) the graphql HOC, and 3) calling watchQuery directly using the client. In all three cases, you provide some query and any appropriate options, and you get a way to initially fetch that query as well as listen to updates to it.

The key here is that queries, and not fragments are the intended vehicles for reading the cache. The readFragment method is only meant as a convenient way to read the cache a single time (usually in the context of changing the cache after a mutation) and does not provide any sort of reactivity.

So, bottom line, wrap your components in either the Query component or the graphql HOC and you will have access to props that reflect the query results in the cache and that will update when the cache updates (the same way connected components do).

At this point a couple of things might be going through your head:

"But I don't need to make another server request!" No worries -- by default, Apollo will only request the same query once, and will use the cache for all subsequent calls. You can modify this behavior by setting the appropriate fetch policy for your query. This includes a cache-only policy that will only pull data from cache (although the default cache-first policy is sufficient for most use cases).

"But I don't have a query to work with!" If you're writing to the cache as a means of persisting some arbitrary client-side state, then you should be using apollo-link-state to do so.

"But I don't need the entire query result, just a part of it!" The graphql HOC provides a props function you can pass in to the configuration that will let you transform your query data into whatever shape you want to work with. The same functionality isn't really needed when using the render props pattern with the Query component -- you can just manipulate the render props directly. In either case, it may be a good idea to write some reducers that you can reuse throughout your project that just take the returned data and transform it into the shape you need. The last big project I worked on did just that client side and it kept things much more manageable.