How do you dynamically control react apollo-client query initiation?

好久不见. 提交于 2020-01-30 19:54:32

问题


A react component wrapped with an apollo-client query will automatically initiate a call to the server for data.

I would like to fire off a request for data only on a specific user input.

You can pass the skip option in the query options - but this means the refetch() function is not provided as a prop to the component; and it appears that the value of skip is not assessed dynamically on prop update.

My use is case is a map component. I only want data for markers to be loaded when the user presses a button, but not on initial component mount or location change.

A code sample below:

// GraphQL wrapping
Explore = graphql(RoutesWithinQuery, {
  options: ({ displayedMapRegion }) => ({
    variables: {
      scope: 'WITHIN',
      targetRegion: mapRegionToGeoRegionInputType(displayedMapRegion)
    },
    skip: ({ targetResource, searchIsAllowedForMapArea }) => {
      const skip = Boolean(!searchIsAllowedForMapArea || targetResource != 'ROUTE');
      return skip;
    },
  }),
  props: ({ ownProps, data: { loading, viewer, refetch }}) => ({
    routes: viewer && viewer.routes ? viewer.routes : [],
    refetch,
    loading
  })
})(Explore);

回答1:


To include an HoC based on a condition affected by a props change, you could use branch from recompose.

branch(
  test: (props: Object) => boolean,
  left: HigherOrderComponent,
  right: ?HigherOrderComponent
): HigherOrderComponent

check: https://github.com/acdlite/recompose/blob/master/docs/API.md#branch

For this specific example, would look something like:

const enhance = compose(
  branch(

    // evaluate condition

    ({ targetResource, searchIsAllowedForMapArea }) =>
      Boolean(!searchIsAllowedForMapArea || targetResource != 'ROUTE'),

    // HoC if condition is true

    graphql(RoutesWithinQuery, {
      options: ({ displayedMapRegion }) => ({
        variables: {
          scope: 'WITHIN',
          targetRegion: mapRegionToGeoRegionInputType(displayedMapRegion)
        },
      }),
      props: ({ ownProps, data: { loading, viewer, refetch } }) => ({
        routes: viewer && viewer.routes ? viewer.routes : [],
        refetch,
        loading
      })
    })
  )
);

Explore = enhance(Explore);



回答2:


I have a similar use case, I wanted to load the data only when the user clicked.

I've not tried the withQuery suggestion given by pencilcheck above. But I've seen the same suggestion elsewhere. I will try it, but in the meantime this is how I got it working based off a discussion on github:

./loadQuery.js

Note: I'm using the skip directive:

const LOAD = `
query Load($ids:[String], $skip: Boolean = false) {
  things(ids: $ids) @skip(if: $skip) {
     title
  }
`

LoadMoreButtonWithQuery.js

Here I use the withState higher-order function to add in a flag and a flag setter to control skip:

import { graphql, compose } from 'react-apollo';
import { withState } from 'recompose';
import LoadMoreButton from './LoadMoreButton';
import LOAD from './loadQuery';

export default compose(
    withState('isSkipRequest', 'setSkipRequest', true),
    graphql(
      gql(LOAD),
      {
        name: 'handleLoad',
        options: ({ids, isSkipRequest}) => ({
          variables: {
            ids,
            skip: isSkipRequest
          },
        })
      }
    ),
)(Button);

./LoadMoreButton.js

Here I have to manually "flip" the flag added using withState:

export default props => (
    <Button onClick={
        () => {
            props.setSkipRequest(false); // setter added by withState
            props.handleLoad.refetch();
        }
     }>+</Button>
);

Frankly I'm a little unhappy with this, as it is introduces a new set of wiring (composed in by "withState"). Its also not battle tested - I just got it working and I came to StackOverflow to check for better solutions.



来源:https://stackoverflow.com/questions/40296800/how-do-you-dynamically-control-react-apollo-client-query-initiation

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!