Coder Social home page Coder Social logo

apollographql / react-apollo Goto Github PK

View Code? Open in Web Editor NEW
6.9K 6.9K 794.0 16.09 MB

:recycle: React integration for Apollo Client

Home Page: https://www.apollographql.com/docs/react/

License: MIT License

JavaScript 100.00%
apollo graphql react redux ssr

react-apollo's Introduction

React Apollo

React Apollo

npm version Build Status Join the community on Spectrum


⚠️ THIS PROJECT HAS BEEN DEPRECATED ⚠️

Please note that 4.0.0 is the final version of all React Apollo packages. React Apollo functionality is now directly available from @apollo/client >= 3. While using the @apollo/react-X packages will still work, we recommend using the following imports from @apollo/client directly instead:

  • old: @apollo/react-components --> new: @apollo/client/react/components
  • old: @apollo/react-hoc --> new: @apollo/client/react/hoc
  • old: @apollo/react-ssr --> new: @apollo/client/react/ssr
  • old: @apollo/react-testing --> new: @apollo/client/testing
  • old: @apollo/react-hooks --> new: @apollo/client

Moving forward, all Apollo + React issues / pull requests should be opened in the apollo-client repo. Please refer to the Apollo Client migration guide for more details.


React Apollo allows you to fetch data from your GraphQL server and use it in building complex and reactive UIs using the React framework. React Apollo may be used in any context that React may be used. In the browser, in React Native, or in Node.js when you want to do server-side rendering.

Documentation

All Apollo Client documentation, including React Apollo usage articles and helpful recipes, lives on https://www.apollographql.com/docs/react/

For the React Apollo API reference, visit https://www.apollographql.com/docs/react/api/react-apollo.html

Maintainers

react-apollo's People

Contributors

amannn avatar anand-sundaram-zocdoc avatar benjamn avatar calebmer avatar danilobuerger avatar doomsower avatar excitement-engineer avatar gforge avatar glasser avatar greenkeeper[bot] avatar helfer avatar hwillson avatar jakedawkins avatar jeshep avatar johnthepink avatar jovidecroock avatar kevinzwhuang avatar leoasis avatar marnusw avatar matthargett avatar peggyrayzis avatar petetnt avatar quentin- avatar renovate-bot avatar renovate[bot] avatar rosskevin avatar shian15810 avatar stevepotter avatar tmeasday avatar vovacodes avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-apollo's Issues

Unexpected APOLLO_QUERY_ERROR fired due to bug in render

If I have an error in the render function of a component that is receiving data from the apollo-client, I see that an APOLLO_QUERY_ERROR action is fired and the bug is captured as the networkError, even though the query did run successfully. An unhandled Promise error is also thrown. The following console output is from Chrome 50:

 action @ 08:27:23.412 APOLLO_QUERY_INIT 
 prev state Object {apollo: Object}
 action Object {type: "APOLLO_QUERY_INIT", queryString: "query sample {↵  viewer {↵    name↵  }↵}↵", query: Object, minimizedQueryString: "query sample {↵  viewer {↵    name↵  }↵}↵", minimizedQuery: Object…}
 next state Object {apollo: Object}

 action @ 08:27:23.435 APOLLO_QUERY_RESULT 
 prev state Object {apollo: Object}
 action Object {type: "APOLLO_QUERY_RESULT", result: Object, queryId: "0", requestId: 1}
 next state Object {apollo: Object}

 action @ 08:27:23.446 APOLLO_QUERY_ERROR 
 prev state Object {apollo: Object}
 action Object {type: "APOLLO_QUERY_ERROR", error: TypeError: Cannot read property 'name' of undefined
    at BadComponent (http://localhost:3000/bundl…, queryId: "0", requestId: 1}
 next state Object {apollo: Object}

Unhandled promise rejection TypeError: Cannot read property 'name' of undefined(…)

I have a simple in-memory example that demonstrates this behavior: https://github.com/NeoPhi/apollo-playground/tree/apollo-error

mapMutationsToProps don't automatically subscribe to store changes

I believe the mapMutationsToProps don't have the state updated unless the mapStateToProps is also present.

To be precise, I have an redux-form that I use the state for input in my mapMutationsToProps. When no mapStateToProps is present, APOLLO_MUTATION_INIT action has empty variables, due to the emptiness of the initial form state. If I use mapStateToProps, the variables is correct with the updated state.

updated: also I had to use mapStateToProps = (state) => ({form: state.form}). I believe that whenever the form gets updated, the component re-render and it makes the mapMutationsToProps be updated with the newest state.

mapQueriesToProps state

In my current implementation, mapQueriesToState gets called the first time with ownProps and state in the object correctly. However, when the store is updated, and the function is called a second time (and each subsequent time), state isn't the redux store state. Instead, it's an object containing the ApolloClient instance, and the store instance:

{
  "ownProps": { // correct },
  "state": {
    "client": { //ApolloClient },
    "store": { //ApolloStore }
  }
}

Server rendering and hydrating apollo store

Hey @stubailo I am exploring the new apollo client with Rails (https://apollo-rails.herokuapp.com/) and was wondering - how the client supports hydrating the store without redux. I see it's react-container is inspired heavily from redux and redux does offer hydrating store while creating the store, but not sure how this works with react-apollo (basic apollo version)? let store = createStore(todoApp, window.STATE_FROM_SERVER)

Apparent redundant check in `connect` file

Hi! First of all great work on the whole apollo platform, following this with high excitement!

I'm just starting to get into the code, debugging the GitHunt app and seeing how things work under the hood. While I was poking around the code in connect, I found this check that I think evaluates to true all the time it is reached, because of the way oldQueries is defined a couple of lines above:
https://github.com/apollostack/react-apollo/blob/master/src/connect.tsx#L241

I'm not sure of the impact of this, I think it's not that big, but maybe it is, and since I'm just getting started to understand all this I'm not sure right now. Anyway, since I saw this, maybe it's useful for you to quickly see if this is ultimately a big issue or not.

Sorry to bother you with this if it happens to be a trivial thing! And again thanks for all the work you've put on this!

mapStatesToProps() NOT working in the latest version.

mapStateToProps() does not work in React-Apollo connect().

The redux state changes are triggered and the change triggers the mapStatesToProps() function. However it stops there.

After hitting the mapStatesToProps(), the changed states do not get passed as props to the underlying components.

All Errors Catched

When using the connect method from react-apollo, all errors that occur in one of the child components, are catched by apollo and fail silently.

Development gets nearly impossible then.

Any ideas why that could be the case?
Using apollo-client 0.3.5 and react-apollo 0.3.3

Thanks!

returnPartialData throws error on empty store

If in mapQueriesToProps I specify returnPartialData: true I get an error thrown from diffFieldAgainstStore saying that Uncaught Error: Can't find field viewer on object [object Object].. I would expect an undefined object to be returned to the view if no data was in the store and returnPartialData was set to true.

Support Context

You are already supporting props and state in the mapQueriesToProps function, but what about context?

Its useful to pass down a varibale from the root to a child without needing to pass the variable as prop into every component.

ROOT > MainLayout > Sidebar > Header > MYCOMPONENT

Inconsistent state in mapMutationsToProps

Originally posted by @deoqc on apollo-client:


I am using redux-form and have 2 forms (lets say FormA and FormB, 'living' in state.form.FormA and state.form.FormB).

The problem is that FormB is not always showing in the state when using mapMutationsToProps, but it is correct in mapStateToProps or in the store (as shown by devtools).


To be more precise, my code is something like this:

const mapMutationsToProps = ({ state }) => ({
  onMutation: () => ({
    mutation: `
      mutation myAwesomeMutation (
        $formKeys: String!
      ) {
        awesomeMutation( 
          formKeys: $formKeys
        ) {
          passThroughtInput
        }
      }
    `,
    variables: {
      formKeys: JSON.stringify(Object.keys(state.form)),
    },
  })
});

and the mutation only returns the same input (passThroughtInput === formKeys)

To check, I also have the following:

const mapStateToProps = (state) => ({
  formKeys: JSON.stringify(Object.keys(state.form)),
});

The callback to the onMutation prints the results on console, and the formKeys is in a Text tag on screen, and also using devtools (so I compare the 3).

As said before, mapStateToProps and store devtools are correct. Mutation is missing (at least most of the time) the state.FormB key (but showing state.FormA).

If you guys don't have any clues, I can try to do a reproducible repo.

Development process

I'm trying to slightly modify the forceFetch behaviour in order to respect the changes in this PR: apollographql/apollo-client#309

But I can't get this project to build with the new typings from apollo-client. @jbaxleyiii can you fill me in on how I'm supposed to bring typings over from apollo-client? I ran node_modules/.bin/typings install but it just brought a bunch of new apollo-client related errors.

Include `variables` in query props

There's currently no way to access variables inside a component wrapped with connect.

It would be great if variables passed to queries in connect() were also passed as a query prop.

E.g:

import React from 'react'

import gql from 'apollo-client/gql'
import { connect } from 'react-apollo'

const MyComponent = { myQuery } => {
  const { items = [], variables, loading, refetch } = myQuery
  const loadMore = () => refetch({
    ...variables,
    skip: variables.skip + variables.limit
  })

  return (
    <div>
      {items.map(item => <div key={item.id}>{item.text}</div>)}

      <button onClick={loadMore}>Load more</button>
    </div>
  )
}

export default connect({
  mapQueriesToProps() {
    return {
      myQuery: {
        query: gql`
          query (
            $limit: Int
            $skip: String
          ) {
            items(
              limit: $limit
              skip: $skip
            ) {
              id
              text
            }
          }
        `,
        variables: {
          limit: 10,
          skip: 0,
        },
      },
    }
  },
})(MyComponent)

Experience with mapQueriesToProps

first i'll say, mapQueriesToProps is pretty cool! To me, this function means we'll be mapping the result of a graphql query. Which in fact we do

{
  loading: false,
  result: {
    posts: []
  }
}

My question is, why tuck it away under a results key? Wouldn't it be nice to just have our prop

{
  loading: false,
   posts: []
} 

I would then in my component much rather do

function App({postsData}) {
  const { posts = [], loading } = postsData;
  if ( loading) {
    return <Loader/>
  }
  return (
    <div>{posts.map(({ title }) => {
      return (
        <div>
          <h1>{title}</h1>
        </div>
      )
    })}</div>
  )
}

const AppWithData = connect({
  mapQueriesToProps() {
    return {
      postsData: {
        query: `
            {
              posts {
                title
              }
            }
          `
      }
    };
  }
})(App);

Essentially when the query yields, can we just extend this state structure? If you guys are down for this change, I can make it happen

Loading component

Currently it is possible to compose components in a way that we show "loading" text when apollo is querying data, based on the "loading" flag.

What would be great it to have a possibility to specify a second component in the connect method, and when this component is specified it would render that component instead of the original one.

Example:

connect({ mapQueriesToProps, mapStateToProps })(MyComponent, LoadingComponent) 

Would you consider this?

Refactor test

Right now the tests are overly verbose in their boilerplate, and they don't accurately test common lifecycle events that can happen with changing props.

Todo:

  • split the connect test into files for prop api, redux integration, queries, and mutations
  • create reusable boilerplate
  • better test lifecycle events

Hopefully this will clean up some issues like #20

Doesn't properly pass through null props somehow

This code doesn't rerender when Meteor.userId() becomes null:

import React, { Component } from 'react';
import { connect } from 'react-apollo';
import { Meteor } from 'meteor/meteor';
import { createContainer } from 'meteor/react-meteor-data';

const App = ({ userId, currentUser }) => {
  console.log(userId, currentUser);
  return (
    <div>
      <LogInButtons />
      { userId ? (
        <div>
          <pre>{JSON.stringify(currentUser, null, 2)}</pre>
          <button onClick={currentUser.refetch}>Refetch!</button>
        </div>
      ) : 'Please log in!' }
    </div>
  )
}

// This container brings in Apollo GraphQL data
const AppWithData = connect({
  mapQueriesToProps({ ownProps }) {
    if (ownProps.userId) {
      return {
        currentUser: {
          query: `
            query getUserData ($id: String!) {
              user(id: $id) {
                emails {
                  address
                  verified
                }
                randomString
              }
            }
          `,
          variables: {
            id: ownProps.userId,
          },
          forceFetch: true,
        },
      };
    }
  },
})(App);

// This container brings in Tracker-enabled Meteor data
const AppWithUserId = createContainer(() => {
  console.log("running", Meteor.userId())
  return {
    userId: Meteor.userId() || false,
  };
}, AppWithData);

export default AppWithUserId;

Wrong props passed to `mapQueriesToProps` and `mapMutationsToProps` on store change

In connect's bindStoreUpdate method, this.props is bound only once:

https://github.com/apollostack/react-apollo/blob/69ce020acbc6b21e43def5e1eca1f36f263e353f/src/connect.tsx#L202

Whenever this.subscribeToAllQueries and this.createAllMutationHandlers are called further down in this method due to store state changes, they receive the probably outdated props bound on initialisation instead of the current value of this.props.

Should I prepare a pull request to fix this?

Make it easy to use Apollo with Redux directly

How does this play well with existing React Redux setups?
What was the design decision here?

Should you be more transparent about whats in this via standalone react redux. If i add this, do I have to remove my current module?

mergeProps with queryProps/mutationProps

Currently the mergeProps function doesn't allow for queryProps or mutationProps.

Will it be different? I find useful to keep the logic in this higher order components. Usually only use map*ToProps but the mergeProps is a must when needed.

Server-side rendering: Create an API for async data fetching

Our goals on server are:

  • fetch all data required for current React tree
  • save data to store
  • do initial render to string with data resolved (ReactDOM.renderToString())
  • send DOM string along with the serialized store state to a client

The main problem here is that, if we have several connected components in a tree, we have to use some sort of waterfall fetching - child component cannot fetch its data until all its parents fetch their queries because there might be different components rendered depending on the props received from the queries. That means, we cannot statically analyze the entire tree in advance and fetch all data in one run, which could negatively affect performance.

Need to investigate how relay addresses the same issue and maybe come up with our own solution here.

Errors regarding synthetic events with basic modification on the starter kit

When clicking on the refetch button on the starter kit I get the following:
https://slack-imgs.com/?c=1&url=http%3A%2F%2Fi.imgur.com%2FbbbbqFA.png

All my packages and npms are up to date in terms of what has been published.

Repo for reproduction:

[email protected]:ciwolsey/apollo-issue-synthetic-events.git

Run this from /imports/ to restore my db:

mongorestore --host 127.0.0.1 --port 3001

Then in browser hit the refetch button and check browser console.

When rendering to string on the server, shouldn't continue to load/re-render

Not sure the above is the best description, but here's a repro:

https://github.com/tmeasday/react-apollo-ssr-repro

To repro:

npm install
npm start

You should see:

> [email protected] start /private/tmp/react-apollo-repro
> babel-node index.js

<div data-reactroot="" data-reactid="1" data-react-checksum="1677794457"><!-- react-text: 2 -->foo <!-- /react-text --></div>
Caught an exception! { [Invariant Violation: React DOM tree root should always have a node reference.] name: 'Invariant Violation', framesToPop: 1 }
Invariant Violation: React DOM tree root should always have a node reference.
    at invariant (/private/tmp/react-apollo-repro/node_modules/fbjs/lib/invariant.js:38:15)
    at Object.getNodeFromInstance (/private/tmp/react-apollo-repro/node_modules/react/lib/ReactDOMComponentTree.js:164:67)
    at [object Object]._assign.getNativeNode (/private/tmp/react-apollo-repro/node_modules/react/lib/ReactDOMTextComponent.js:146:50)
    at Object.ReactReconciler.getNativeNode (/private/tmp/react-apollo-repro/node_modules/react/lib/ReactReconciler.js:64:29)
    at ReactDOMComponent.ReactMultiChild.Mixin._updateChildren (/private/tmp/react-apollo-repro/node_modules/react/lib/ReactMultiChild.js:319:42)
    at ReactDOMComponent.ReactMultiChild.Mixin.updateChildren (/private/tmp/react-apollo-repro/node_modules/react/lib/ReactMultiChild.js:276:12)
    at ReactDOMComponent.Mixin._updateDOMChildren (/private/tmp/react-apollo-repro/node_modules/react/lib/ReactDOMComponent.js:883:12)
    at ReactDOMComponent.Mixin.updateComponent (/private/tmp/react-apollo-repro/node_modules/react/lib/ReactDOMComponent.js:712:10)
    at ReactDOMComponent.Mixin.receiveComponent (/private/tmp/react-apollo-repro/node_modules/react/lib/ReactDOMComponent.js:668:10)
    at Object.ReactReconciler.receiveComponent (/private/tmp/react-apollo-repro/node_modules/react/lib/ReactReconciler.js:127:22)

I would expect it to render but not throw an error because it tries to re-render after the query completes.

Caching

Dears, this is more of a question than issue.

Current functionality maps the query to react component. This, whenever is displayed fetches new data from the server. While this is OK for many cases, it would be great to have a decision mechanism to use cached data. For example, I can cache data in the store and then in the container I can decide whether to use cached data or get fresh data.

Do you have any advice on implementation?

In the core I've found a way of how to perform a query, but there are just too many possibilities on how to approach this. Would love to hear from you guys.

API simplifications

I find the API to expose Apollo state to UI components too complex, especially considering that this is an operation we’ll have to do for almost every single component. So I’ll start with an example and share some iterative improvement ideas; here it is:

const TopicHeader = connect({
  mapQueriesToProps({ ownProps }) {
    return {
      topic: {
        query: gql`
          query getTopic ($topicId: ID) {
            oneTopic(id: $topicId) {
              id
              category_id
              title
            }
          }
        `,
        variables: {
          topicId: ownProps.topicId,
        }
      }
    }
  },
})(RawTopicHeader);

It’s clear from this example that a lot of code is duplicated, but there is actually a good reason for that which is that some symbols live in the JS world and some in the GraphQL world (eg { query: 'query ...' }). And that’s a hard problem in term of API design. For instance we could try to remove the GraphQL line query getTopic ($topicId: ID) { and have Apollo generate this wrapper automatically with the informations from the JavaScript world, but that’s wouldn’t be suitable because the abstraction doesn’t match in a 1..1 relation (JS doesn’t have types for instance). I just wanted to emphasize this problem because other similar in-scope libraries like OM/next doesn’t encounter it. They use the same language (ClojureScript) for the wrapper file and the query specification, and that allows them to create a perfect API with no duplicate symbols.

So back to my above example, I still think that there is room for improvements, and I’ll try to iterate on it but I may be wrong at some specific step so my goal is more to open a discussion than to provide a concrete proposal.

The first thing I would like to remove is the topic JavaScript variable as I believe we could rely exclusively on the GraphQL names as we do for non-top-levels names like category_id or title. Since in this specific example the JS name (topic) and the GQL name (oneTopic) doesn’t match we need to rename the field in GraphQL:

const TopicHeader = connect({
  mapQueriesToProps({ ownProps }) {
    return {
      query: gql`
        query getTopic ($topicId: ID) {
          topic: oneTopic(id: $topicId) {
            id
            category_id
            title
          }
        }
      `,
      variables: {
        topicId: ownProps.topicId,
      }
    }
  },
})(RawTopicHeader);

The rename really isn’t anything fancy, it’s what we would do for any inner GraphQL field anyway, so it’s more consistent to do it for this top-level name as well. Removing the symbol in the JS space also doesn’t remove anything in term of code editor features because the symbol will be exposed as a component argument as it was prior to this change:

const RawTopicHeader = ({ topic }) => {
  return (<div><h1>{topic.title}</h1></div>)
}

Generally speaking I think that using function arguments as the fence between JS and GQL symbols would be a useful API principle.

The next step might be more controversial but I believe there is some value is switching to a static query instead of dynamically computing it—which should be exclusive to the “variables” part. Static data requirements would be useful to various dev tools and to compose queries without instantiating the related components. So basically we would write something like this:

const TopicHeader = exposeGQL({
  query: gql`
    query getTopic ($topicId: ID) {
      topic: oneTopic(id: $topicId) {
        id
        category_id
        title
      }
    }
  `,
  variables: function(ownProps) {
    return {
      topicId: ownProps.topicId,
    };
  }
})(RawTopicHeader);

Only the variables part is computed, the query is static. I’ll do a little digression to address the (rare?) cases where the data specification depends on some component props, for instance:

const UserName = connect({
  mapQueriesToProps({ ownProps }) {
    if (ownProps.anonymousUser) {
      return {};
    } else {
      return {
        query: gql`
          query getUser ($userId: String!) {
            user(id: $userId) {
              name
            }
          }
        `,
        variables: {
          userId: ownProps.userId,
        }
      }
    }
  },
})(RawUserName);

Here if the user is anonymous we don’t want to send a query to the server asking the user name because we already now that this information doesn’t exist. I can think of two solutions to handle this case:

  1. Use the @skip and @include directives, that would be something like

    const Username = exposeGQL({
      query: gql`
        query getUser ($skipFetching: Boolean!, $userId: String!) {
          user(id: $userId) @skip(if: $skipFetching) {
            name
          }
        }
      `,
      variables: function(ownProps) {
        return {
          skipFetching: ownProps.anonymousUser
          userId: ownProps.userId,
        };
      }
    })(RawUsername);

    I’m not super fan of this solution as it sounds a bit like cheating: instead of writing a simple if condition, we have to introduce a weird GraphQL directive to express statically that’s we want to skip a query when executed;

  2. Another possibility would be to not specify that we want to skip the query fetching and let the Apollo client figuring that out for us, as follows:

    const Username = exposeGQL({
      query: gql`
        query getUser ($userId: String!) {
          user(id: $userId)
            name
          }
        }
      `,
      variables: function(ownProps) {
        return {
          userId: ownProps.anonymousUser ? null : ownProps.userId,
        };
      }
    })(RawUsername);

    Here we don’t explicitly say that we want to skip the user fetching, but as we don’t pass a valid userId to the GraphQL query (we are passing null whereas a string is expected), there is no way the GraphQL server will return a user from that invalid query and so the Apollo client could avoid the query roundtrip. Consequently the user will be undefined in the UI component, which is what we want in this case.

I don’t want to expend too much on this particular issue of expressing dynamic requirements with static queries (it’s already a big parenthesis), there are probably many other solutions and I believe that a majority (all?) of UI components could express their data requirements in a static way.

Back to the original example, here is the code as we left it before the digression:

const TopicHeader = exposeGQL({
  query: gql`
    query getTopic ($topicId: ID) {
      topic: oneTopic(id: $topicId) {
        id
        category_id
        title
      }
    }
  `,
  variables: function(ownProps) {
    return {
      topicId: ownProps.topicId,
    };
  }
})(RawTopicHeader);

To avoid repeating the world query twice, we could simply switch to ordered function arguments. The first argument is the GraphQL query, the second one is the variables mapping—like this:

const TopicHeader = exposeGQL(gql`
  query getTopic ($topicId: ID) {
    topic: oneTopic(id: $topicId) {
      id
      category_id
      title
    }
  }`,
  function(ownProps) {
    return {
      topicId: ownProps.topicId,
    };
  }
)(RawTopicHeader);

and for stylistic concision only, we would use an ES6 arrow function for the variables mapping:

const TopicHeader = exposeGQL(gql`
  query getTopic ($topicId: ID) {
    topic: oneTopic(id: $topicId) {
      id
      category_id
      title
    }
  }`, 
  (props) => ({
    topicId: props.topicId,
  })
)(RawTopicHeader);

At this point we already gained a lot of concision, one last step (that is maybe too much?) would be to make the second argument (the mapping) optional by providing a default value: the identity function ((props) => props) that would expose the components props to the GraphQL query variables. Thus, the mapping function would be skipped for the most simple components. In our case:

const TopicHeader = exposeGQL(gql`
  query getTopic ($topicId: ID) {
    topic: oneTopic(id: $topicId) {
      id
      category_id
      title
    }
  }
`)(RawTopicHeader);

And that’s it, I’m pretty happy with this last snippet :-)

I’m sorry for the very long text, I thought it was useful to share my thought process to facilitate the discussion about potential API simplifications.

Multiple queries

Does react-apollo not support multiple queries or is it graphql?

Refetching query from component returns "loading: true"

After fetching a query using mapQueriesToProps(), If I refetch the query from the React Component, the returned query has "loading: true" and it never resets to "loading: false" even though the loading is clearly finished.

While on the subject, is the best way to trigger a data refresh by doing a .refetch() inside the react component when its appropriate to do so?

mapStateToProps params

It looks like mapStateToProps currently gets called with just the redux state. The docs show that it gets called with an object containing ownProps and state. Is it intended to contain ownProps as well? Or should we update the docs? cc @jbaxleyiii

Bug when upgrading to 0.3.4

First referenced here.


When upgrading to 0.3.4, app just slows down way too much. The XCode console (using React Native) just spiting a lot of things like this bellow:

equalObjects@http://localhost:8081/index.ios.bundle?platform=ios&dev=true:69878:31
baseIsEqualDeep@http://localhost:8081/index.ios.bundle?platform=ios&dev=true:69668:20
baseIsEqual@http://localhost:8081/index.ios.bundle?platform=ios&dev=true:69610:23
equalObjects@http://localhost:8081/index.ios.bundle?platform=ios&dev=true:69878:31
baseIsEqualDeep@http://localhost:8081/index.ios.bundle?platform=ios&dev=true:69668:20
baseIsEqual@http://localhost:8081/index.ios.bundle?platform=ios&dev=true:69610:23
equalObjects@http://localhost:8081/index.ios.bundle?platform=ios&dev=true:69878:31
baseIsEqualDeep@http://localhost:8081/index.ios.bundle?platform=ios&dev=true:69668:20
baseIsEqual@http://localhost:8081/index.ios.bundle?platform=ios&dev=true:69610:23
isEqual@http://localhost:8081/index.ios.bundle?platform=ios&dev=true:70038:19
http://localhost:8081/index.ios.bundle?platform=ios&dev=true:69118:12
dispatch@http://localhost:8081/index.ios.bundle?platform=ios&dev=true:68541:13
dispatch@http://localhost:8081/index.ios.bundle?platform=ios&dev=true:82792:21
http://localhost:8081/index.ios.bundle?platform=ios&dev=true:71511:21
dispatch@http://localhost:8081/index.ios.bundle?platform=ios&dev=true:68892:17
fetchQuery@http://localhost:8081/index.ios.bundle?platform=ios&dev=true:73879:20
startQuery@http://localhost:8081/index.ios.bundle?platform=ios&dev=true:73933:16
http://localhost:8081/index.ios.bundle?platform=ios&dev=true:73777:29
subscribe@http://localhost:8081/index.ios.bundle?platform=ios&dev=true:78901:58
subscribe@http://localhost:8081/index.ios.bundle?platform=ios&dev=true:73702:39
handleQueryData@http://localhost:8081/index.ios.bundle?platform=ios&dev=true:69220:40
subscribeToAllQueries@http://localhost:8081/index.ios.bundle?platform=ios&dev=true:69163:21
componentWillMount@http://localhost:8081/index.ios.bundle?platform=ios&dev=true:69085:27
mountComponent@http://localhost:8081/index.ios.bundle?platform=ios&dev=true:15996:24

I'm currently trying to make a reproducible repo.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.