apollographql / apollo-link-state Goto Github PK
View Code? Open in Web Editor NEW✨ Manage your application's state with Apollo!
License: MIT License
✨ Manage your application's state with Apollo!
License: MIT License
I am very new to graphql and apollo. So please excuse if this question seems trivial. Also this may well be the wrong place to ask as it surely is a general graphql question. But it applies for me only when working with local state.
I am trying to use apollo-link-state to replace my mobx store.
In this store there are a number of simple variables, for instance: activeObject
. Which is the id of the object presently shown in the detail page.
Your example shows managing local state for a list or array of todos.
Somehow I have not been able to grasp how I would manage state for a single value, such as activeObject
.
Of course I can use an array containing only a single value. But that seems just wrong.
How would one manage single values in the store?
I added graphql-tag
in README.md.
It's not working: import { gql } from 'react-apollo';
Intended outcome:
Example app has a TopComponent
, which executes query. This component has a nested BottomComponent
, which also executes the same query.
I expect BottomComponent
to render only once since data is fetched from cache or at least to have some kind of loading
/ complete
state.
Actual outcome:
TopComponent
executes query. When loading
prop is false, BottomComponent
is rendered. It takes query from cache and renders the same component twice with the same props.
How to reproduce the issue:
The app is as simple as that:
// App
const App = () => {
const networkInterface = createNetworkInterface({
uri: 'http://admin.localhost:3000/graphql'
})
const apolloClient = new ApolloClient({ networkInterface })
const store = configureStore(apolloClient)
console.log('render app')
return (
<ApolloProvider store={store} client={apolloClient}>
<TopComponent />
</ApolloProvider>
)
}
// TopComponent
const TopComponent = ({ data: { loading, error } }) => {
console.log('render top component', loading, error)
if (loading) {
return <p>loading</p>
}
if (!loading && error) {
return <p>error</p>
}
console.log('before render bottom component')
return (
<BottomComponent />
)
}
export default graphql(query)(TopComponent)
// BottomComponent
const BottomComponent = ({ data: { loading, error } }) => {
console.log('render bottom component', loading, error)
return (
<p>bottom component</p>
)
}
export default graphql(query)(BottomComponent)
The result output:
As you can see, BottomComponent
renders twice with the same props.
Version
Hello! I don't know how to make it better. Please help.
I use the function:
async update() {
let variables = {
company: this.props.match.params.companyId,
filter: this.filter, order: this.order, limit: this.pagiation.limit, offset: this.pagiation.offset
};
await this.props.refetch(variables);
}
But I see in Network two queries and nothing happens.
The first one is right, but the second is the default data (like variables: { company: props.match.params.companyId, filter: {}, order: [], limit: 10, offset: 0 }
). Why?
@ApolloReact.graphql(ApolloReact.gql"
query Departments($company: ID!, $filter: DepartmentFilter!, $order: [DepartmentOrder], $limit: Int, $offset: Int) {
company {
get(id: $company) {
id,
name,
color,
departments {
list(filter: $filter, order: $order, limit: $limit, offset: $offset) {
departments {
id,
color,
name,
users {
id, avatar, username
},
tags {
name
},
date
},
count
}
}
}
}
}", {
props: ({ ownProps, data: { loading, company, refetch } }) => ({
company: company && company.get,
departments: company && company.get && company.get.departments && company.get.departments.list.departments,
count: company && company.get && company.get.departments && company.get.departments.list.count,
loading: loading,
refetch: refetch
}),
options: (props) => ({
fetchPolicy: 'cache-and-network',
variables: { company: props.match.params.companyId, filter: {}, order: [], limit: 10, offset: 0 }
}),
})
But if I call console.log(await this.props.refetch(variables));
this is what I need, but I want to see it in props
.
async update() {
let variables = {
company: this.props.match.params.companyId,
filter: this.filter, order: this.order, limit: this.pagiation.limit, offset: this.pagiation.offset
};
console.log(await this.props.refetch(variables));
}
This Pull Request updates dependency [react-scripts-ts](https://github.com/wmonk/create-react-app) from v2.4.0
to v2.8.0
Note: This PR was created on a configured schedule ("after 10pm every weekday,before 5am every weekday" in timezone America/Los_Angeles
) and will not receive updates outside those times.
ce4406a
v2.8.02392778
Merge pull request #170 from nicolaserny/masterbeb1381
Upgrade to typescript 2.5.3606b651
v2.7.03cf5427
Update README For 2.7.028447ee
Merge pull request #157 from JohnNilsson/facebook-1.0.13fa89c00
change version back to 2.6.026979d3
Set travis config to use 'precise' ci environment51ee648
Publishe8c952d
Changelog for 1.0.13ec2f824
Add missing slash638a81c
Make error overlay filename configurable (#3028)c4651dc
provide empty mock for child_process so importing libraries with it works (#3033)763c4c2
Rename Overlay to ErrorOvelay (#3051)563ff66
Strip hash from chunk file name (#3049)912a02e
Fix error overlay 'Object.assign' issue in IE by including polyfills before webpack client (#3046)ef01aab
Publish5904d88
Changelog for 1.0.12 (#3016)169ef76
Relax React dep requirementsee75676
Default Favicon lossless optimisation (#2917)6aba427
update babel-runtime dependency in react-error-overlay and react-scripts (#2991)caa9cef
Convert react-error-overlay to React (#2515)acd639d
Bump react-dev-utilsae457ae
Fix module function name in error overlay (#3012)7aa5c2c
Docs: debugging in WebStorm (#2986)152ef9b
Fix docs for printFileSizesAfterBuild
(#2942)da055d6
Remove Modulus from user guide (#2948)f9c601b
Remove superfluous lodash usage (#2938)72bcf33
Update README.md (#2927)9a6e32d
Delete leftover file (upstream 82687dd)0bb9537
Publish8561285
Prepare for 1.0.11 release (#2924)8ace6d5
Update dev deps (#2923)2d76563
Update README.md2ff3a19
Use env variable to disable source maps (#2818)b2593b6
Make formatWebpackMessages return all messages (#2834)dcdab42
Adjust the checkIfOnline
check if in a corporate proxy environment (#2884)dba32be
Fix the order of arguments in spawned child proc (#2913)eb3f85d
Feature/webpack 3 4 (#2875)9b79012
Allow importing package.json (#2468)de46152
Re-enable flowtype warning (#2718)e08b789
Format UglifyJs error (#2650)adb4c6d
Unstage yarn.lock pre-commit (#2700)de34cf6
Update README.md791df18
Update README.md2c988b9
Fix parsing HTML/JSX tags to real elements (#2796)a6cd6f3
Update webpack version note (#2798)3cd4747
Use modern syntax feature (#2873)8dad81d
Allow use of scoped packages with a pinned version (#2853)27f1256
Bump Webpack 3.4 (#2850)c93e630
Feature/webpack3 (#2574)64e5869
Add explicit "Opting Out of Caching" header (#2822)834515f
Upgrade webpack-dev-server (#2806)777e70a
List conflicting files when initializing app (#2785)c3f4b7c
Moved npm run build before npm test (#2725)494d96f
Docs for react-router v4 basename feature (#2668)5eb7c73
Don't prompt to install serve if already installed (#2761)772a447
Autodetect JetBrains IDEs (#2754)e0c2729
Use Rule.oneOf to resolve correct loader (#2747)63e8924
ESLint 4 (#2735)31e3ffe
Add "node" to Jest's moduleFileExtensions (#2738)4b856a7
Support PyCharm in launchEditor (#2740)fee4e57
Update link to issue blocking JSX hoisting (#2732)fc2057c
Reorder vim arguments in launchEditor so --remote works (#2723)028b5c5
Remove Windows note for source-map-explorer (#2719)c8cb004
allowTaggedTemplates to avoid warnings from SC's (#2701)ae40264
Publish142dfe4
Merge pull request #149 from JReinhold/doc_migration_to_2.5.0de25bd7
fixed typo in migrationa32ac09
Merge pull request #150 from hktonylee/fixed_merge_typo_ISSUE_TEMPLATE.md1d83191
changed list number in ISSUE_TEMPLATE.md14d0ec4
added migration steps to v2.5.0e87df91
Merge pull request #143 from swengorschewski/dependenciesd0d5133
Merge pull request #145 from comerc/patch-1966d59f
fixed merge typo in ISSUE_TEMPLATE.mdf140f88
Fixed VSCode warning for tslint trailing-comma6ae7751
Install typings as dev dependencies34d0726
Update README.md for v2.6.06b4331d
v2.6.052fbee9
Merge pull request #104 from wmonk/facebook-1.0.103afca81
! PUBLIC_URL4dad65c
Default to empty string for PUBLIC_URLf2a5c5f
Fix tslint7014aed
Fix Code Review4d9c829
Changelog for 1.0.10 (#2694)d6025a3
Update CHANGELOG.md07347f2
Upgrade flow (#2693)3bc8dcd
Downgrade strip-ansi
package to 3.0.1 (#2692)7db4e87
Fix typo (#2683)ed23d62
Fix typo in README link (#2684)d5da1e8
Changelog for 1.0.9 (#2682)761fe6f
Fix external CSS imports (#2680)a720aa0
Fix minor typo (#2679)03a52d4
Bootstrap with Yarn when available (#2673)6cafdfc
Add more info about apache client side routing (#2666)3ad87f7
Test Node 8 on Travis (#2659)22a9503
Add json and css to lint-staged in template README (#2671)6bf95f2
Add a note about fixed vulnerability in 1.0.88d156ed
PublishThis PR has been generated by [Renovate Bot](https://renovateapp.com).
I'm finding it hard to select data from my redux store that depends on both, current redux state and data fetched by Apollo.
An example is the following: I have an options
model, which has id, name
properties. These options
are fetched by apollo from the server. In a form, I have a select field, in which I store a selected option ID (which I use in a mutation, to change the currently selected option).
Now, sometimes I need to pass the currently selected option (stored in redux) name, to another component, for this, I have to do something a bit ugly like the following:
const optionNameSelector = ({ options, optionId }) => options.find(option => option.id === optionId);
// And in the component I want:
// ...
const optionName = optionNameSelector({ options: data.options, optionId: state.optionId });
<MyComponent optionName={optionName} />
So my component has to know where to get the options
from, instead of being able to just pass the whole state or something like that.
What's a better solution for this? I think having a denormalized apollo state in the redux store would be nice.
I was just chatting about these ideas with @stubailo and he suggested I file an issue.
I think one of the aspects that makes apollo-link-state potentially more powerful and expressive than other state management solutions like Redux is the ability for server state and client state to nest with each other. For example, imagine this query for a todo list where items can be selected as part of client-side state:
query list {
list(name: "my list") {
items {
name
isDone
isSelected @client
}
}
}
Getting the per-item local state nicely nested inside the server-side state in your component's data prop would be super convenient!
My actionable suggestion is that we build something like this as one of the motivating (and tested) examples for apollo-link-state. (I don't have the time to actually help with this myself, unfortunately.) It doesn't necessarily need to be the main example: @stubailo pointed out that we don't want folks to think that apollo-link-state is only useful for cross-source nested data. But we definitely should make sure it's natural and easy to do things like this, in my opinion!
Hey guys, i have this problem:
There's a list with 600~ items loaded from the server. now, every row has a button, and on press it calls a mutation.
After calling the mutation, the app "freeze"/fps drop untill the mutation is done.
i tried sending only 10 items to the list, but still, the app freeze. and when i sent from the server only 10 items and displayed them - it worked good, no "freeze"/fps drops.
so the only difference here is the amount of data saved in the store behind the scenes (aka cache).
Intended outcome:
The app will work smoothly while the mutation works behind the scenes
Actual outcome:
Calling the mutation results in heavy fps drop/slowness
How to reproduce the issue:
Im not sure there's easy way to have an example app using apollo gql, if there's then ill create one.
otherwise, you need to have alot of items in the apollo store (probably by getting the data from a server) and mutate a row
Version
how to connect the link-state when we already started the createHttp link?
my snipped goes like this
const link = createHttpLink ({
uri: "http://localhost: 4000/graphql",
link: withClientState(schema),
credentials: "include"
});
const client = new ApolloClient ({
link,
cache: new InMemoryCache()
});
but it still does not work!
I mostly want to open this PR for the sake of conversation. I can't for the life of me figure out why this logic exists inside of react-apollo, and it seems to be causing issues for many users as pointed out in #556.
I'm interested in some feedback, as I have not been using apollo for long, and it's not clear to me why the desired fetchPolicy
would be changed despite what the developer intends.
Intended outcome:
Upgrading from 1.x release to the 2.x release.
Actual outcome:
Types of property 'client' are incompatible.
Type 'ApolloClient<NormalizedCache>' is not assignable to type 'ApolloClient<Cache>'.
Type 'NormalizedCache' is not assignable to type 'Cache'.
Property 'add' is missing in type 'NormalizedCache'.
How to reproduce the issue:
Install react apollo in a typescript project and run tsc
Version
Following up those issues: apollographql/react-apollo#238 and https://github.com/apollographql/react-docs/issues/56, it seems like there is no a built-in way to create X mutations where X is NOT a fixed number in one Request.
For Instance, assume that on FB we want to select friends suggestion and add them, in that case, I would like to send X mutations to the server all in one request, one per friend added (Having one mutation on the server that receives an array and executes the operation is not an option). Something like:
m1: graphql(addFriend, { user_b: ‘a' }),
m2: graphql(addFriend, { user_b: ‘b' }),
m3: graphql(addFriend, { user_b: ‘c' }),
...
mN: graphql(addFriend, { user_b: ‘r' }),
If we don’t know the number of mutations the client should do, how can we implement this with Apollo?
Note 1: In this case, all mutations will be the same mutation (addFriend) with different params.
Note 2: All should be in the same request
Intended outcome:
Upgrading from 1.x release to the 2.x release.
Actual outcome:
Error at node_modules/react-apollo/browser.d.ts:6:26: Could not find a declaration file for module 'lodash.flowright'. '/Users/x/x/node_modules/lodash.flowright/index.js' implicitly hasan 'any' type.
Try `npm install @types/lodash.flowright` if it exists or add a new declaration (.d.ts) file containing `declare module 'lodash.flowright';`**How to reproduce the issue:**
Install react apollo in a typescript project and run tsc
Version
I created an example using flow. Hopefully it will be useful for people to have a reference on how to implement flow in react-apollo.
I ran into a couple of issues trying to create this example:
OperationComponent
type definition from react-apollo. Therefore, the wrapped component’s props aren’t typed properly.Anyone have any ideas on a solution to the issues I mentioned?
I was also wondering whether the type definitions in react-apollo can also be used for mutations. I haven’t found any docs for this. I would be glad to help document these definitions and include them in this example repo.
So, I the client option was merged where users can pass in a Client to override the client in ApolloProvider. One pain that I've come across using this method is that for SSR, it's complicates things when you need to create a new client per HTTP request. Without multiple clients, in typical react-apollo setups, this works fine because each request wraps the app in ApolloClient, runs getDataFromTree, etc, etc. When using SSR, this example in the comments when the client option was originally merged makes it difficult (because the cache is somewhat lost, unless you pass around the original created one)
Current Implementation:
// This is fine on the browser since you can locally cache "other-client"
// and re-use... but a pain for SSR.
import MyOtherClient from "../other-client"
export default graphql(MyQuery, {
client: MyOtherClient,
})(MyComponent);
This PR adds this functionality:
// Store.js
export default graphql(gql(`...`))(Products); // uses default client
// Repositories.js
export default graphql(gql(`...`), {
options: {
client: 'github'
}
})(Repos);
// App.js
<ApolloProvider clients={{ shopify, github }} defaultClient={shopify}>
<App>
<Store />
<Repositories />
</App>
</ApolloProvider>
I know I'm supposed to create PRs only if there's a consensus, but it was more of a pain setting up an environment to show my use-case than it was to just see if moving all clients to the provider context would fix it. After I added all of this, it indeed fixed my issue where double fetching on the server & browser would happen.
This still needs a few more tests and error handling when clients with invalid names don't exist, etc.
apollographql/react-apollo#1232
I still need to add a few more tests and clean things up.
Intended outcome:
The typescript definition of ChildProps.data
should be non-optional, since according to the documentation (http://dev.apollodata.com/react/api-queries.html#graphql-query-data) the data
property has a loading
/error
subproperty to check for completion/errors.
Actual outcome:
The actual type definition is
export declare type ChildProps<P, R> = P & {
data?: QueryProps & R;
mutate?: MutationFunc<R>;
};
forcing users to always check if data
is defined before being able to access data.loading
or other properties.
One example from the documentation
render() {
const { data: { loading, error, todos } } = this.props;
if (loading) {
return <p>Loading...</p>;
} else if (error) {
return <p>Error!</p>;
} else {
return (
<ul>
{todos.map(({ id, text }) => (
<li key={id}>{text}</li>
))}
</ul>
);
}
}
would fail if using typescript because of data?
.
Version
I'm create an example react-native app to use apollo, and connect to https://my.domain.name/graphql
, It's work on iOS simulator but when i running on Android Emulator or Android physical device it doesn't works, error is appear like this
Unhandled (in react-apollo) Error: Network error: Network request failed
at new ApolloError (http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:61358:32)
at ObservableQuery.currentResult (http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:61488:29)
at GraphQL.dataForChild (http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:58649:66)
at GraphQL.render (http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:58700:37)
at finishClassComponent (http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:4402:112)
at updateClassComponent (http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:4395:338)
at beginWork (http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:4501:28)
at performUnitOfWork (http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:5412:24)
at workLoop (http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:5431:125)
at Object._invokeGuardedCallback (http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:2524:18)
this's my code
const networkInterface = createNetworkInterface({
uri: 'https://my.domain.name/graphql',
opts: {
credentials: 'same-origin',
}
});
this.client = new ApolloClient({
networkInterface
});
and this query
export default graphql(gql`
query {
post(start: 0, offset: 5) {
id
}
}
`)(MainScreen);
Intended outcome:
I would like for my React app to render once on either side. Once on the server, get the state -> hydrate on client and render once.
It could end up causing quite a performance hit if I am essentially rendering my app 4 times for every request.
Actual outcome:
I've set up a simple console.log("Rendering App")
in my App
render method. It shows that while the server is serving the request my app is rendering twice and also on the client my app is rendering twice:
It only happens when I use getDataFromTree()
on the server side and on the client side it only occurs when I create my ApolloClient
using an initial state in the options, in my case like this: initialState: window.__APOLLO_STATE__
.
There are no other network requests going out from the client, so no queries being enacted etc. which might cause a re-render.
I managed to find the render methods being called in Chrome Devtools:
You can see the first App.render
a bit on the left there and the final (much shorter one) is on the right there in the blue bordered block
Both of those App.render
methods happen almost directly after a proxiedMethod
and GraphQL.render
method.
How to reproduce the issue:
On the server (the method that returns all the stuff I place into my HTML response):
const apolloClient = new ApolloClient({
ssrMode: true,
networkInterface: createNetworkInterface({
uri: "https://api.graph.cool/simple/v1/cj6dds6fd2t2z0101yktqzgsd",
}),
});
console.log("Rendering to React");
const app = wrapAppComponent(App, apolloClient);
await getDataFromTree(app);
const appHtml = renderToString(app);
return { reactHtml: appHtml, reactState: {apollo: apolloClient.getInitialState()} };
On the client:
const apolloState = window.__APOLLO_STATE__;
const networkInterface = createNetworkInterface({
uri: "https://api.graph.cool/simple/v1/cj6dds6fd2t2z0101yktqzgsd",
});
const client = new ApolloClient({
networkInterface,
initialState: apolloState,
ssrForceFetchDelay: 100,
});
Version
This PR updates README.md from 1.0. usage closer to the 2.0. setup & usage from https://www.apollographql.com/docs/react/basics/setup.html.
The texts might need some rework though.
Hi,
We are trying to implement react-apollo
in our react app 🎉 one of the blocker that we came across is:
How can I tell the apollo-client
that I want the data stored into redux-store
as an immutable object?
So that i can access it in this way:
const MyGqlComponent = ({data}) {
return <div>data.myquery.get('myField')</div>;
}
I remember in the previous versions there was a prop called immutable
available in the ApolloProvider
that allowed me to do exactly that!
it doesn't seem to be there anymore, any help please
Hello,
when I use refetech loading is not updated to true and after fetch to false. Is it issue or I'm doing something wrong?
const FoldersContainerWithGraphQL = compose(
withApollo,
graphql(GET_FOLDERS_REVIEW, {
options: () => {
return {
variables: {limit: FOLDERS_PER_PAGE, offset: 0}
};
},
props: ({data, data: {fetchMore}}) => {
return {
folders: {
...data,
loadMoreEntries(pageNumber) {
return fetchMore({
variables: {
offset: FOLDERS_PER_PAGE * pageNumber
},
updateQuery: (previousResult, {fetchMoreResult}) => {
if (!fetchMoreResult) {
return previousResult;
}
return fetchMoreResult;
}
});
}
}
};
}
})
)(FoldersContainer);
After unmounting a component wrapped with a query, the query remains watched in InMemoryCache
. It leads to a major performance issue since writing to the cache (and so broadcasting watches) takes more and more time after each component mounting/unmounting.
To reproduce this you can just mount and then unmount many times a component wrapped with any QraphQL query and look at this.watches.length
in InMemoryCache
object.
Version
Intended outcome:
For illustration, use this HOC:
const withDependency = graphql(DependencyQuery,
{
skip: ({dependency}) => !dependency || !dependency.id,
options: ({dependency}) => ({
variables: {
id: dependency.id
}
})
}
)
I expect options to not be evaluated as a result of the skip
test failing.
Actual outcome:
options
is called when dependency
doesn't exist, resulting in a javascript prop access error.
Version
I have an such insert code.
this.subscription = [subscribeToMore({
document: postInserted,
updateQuery: (previousResult, {
subscriptionData
}) => {
Object.preventExtensions(previousResult);
/* ! error line --> */ previousResult.posts.push(subscriptionData.data.postInserted);
return previousResult
},
}),
I get this error
TypeError: Cannot add property 2, object is not extensible
how can I solve this error?
Hey,
i got a bunch of flow errors with the following versions.
Intended outcome:
No flow errors
Actual outcome:
53 errors, like that:
Error: node_modules/apollo-client/node_modules/graphql/validation/rules/OverlappingFieldsCanBeMerged.js.flow:637
637: return type1 instanceof GraphQLList ?
^^^^^^^^^^^ GraphQLList. This type is incompatible with
628: type1: GraphQLOutputType,
^^^^^^^^^^^^^^^^^ union: GraphQLScalarType | GraphQLObjectType | GraphQLInterfaceType | GraphQLUnionType | GraphQLEnumType | type application of class `GraphQLList` | type application of class `GraphQLNonNull`**How to reproduce the issue:**
New project with flow, react-apollo, apollo-client.
.flowconfig
[ignore]
[include]
[libs]
[lints]
[options]
esproposal.decorators=ignore
Version
I have an existing wrapped component that uses a query. I'm trying to change it to a mutation, but I'm getting errors.
Intended outcome:
I would expect the code below to work as-is.
Actual outcome:
The error from the console is
Main.cjsx:114 Error: Must contain a query definition.
at getQueryDefinition (getFromAST.js:75)
at QueryManager.watchQuery (QueryManager.js:424)
at ApolloClient.watchQuery (ApolloClient.js:183)
at GraphQL.createQuery (react-apollo.browser.umd.js:437)
at GraphQL.updateQuery (react-apollo.browser.umd.js:454)
at GraphQL.componentWillReceiveProps (react-apollo.browser.umd.js:312)
at ReactCompositeComponent.js:611
at measureLifeCyclePerf (ReactCompositeComponent.js:75)
at ReactCompositeComponentWrapper.updateComponent (ReactCompositeComponent.js:610)
at ReactCompositeComponentWrapper.receiveComponent (ReactCompositeComponent.js:547)
at Object.receiveComponent (ReactReconciler.js:125)
at Object.updateChildren (ReactChildReconciler.js:109)
at ReactDOMComponent._reconcilerUpdateChildren (ReactMultiChild.js:208)
at ReactDOMComponent._updateChildren (ReactMultiChild.js:312)
at ReactDOMComponent.updateChildren (ReactMultiChild.js:299)
at ReactDOMComponent._updateDOMChildren (ReactDOMComponent.js:936)
I believe these errors are triggered because we provide a client in the options rather than using the default client (we're calling multiple GraphQL services from our UI).
Here's the failing code:
import {graphql, gql} from 'react-apollo'
import InspectionFailure from './InspectionFailure'
import client from '../../inspections/graphQLClient'
//language=GraphQL
const compiledQuery = gql`
mutation runInspections($groupId: String!) {
triggerAutomaticInspectionsOn(entityType: Group, entityId: $groupId) {
results {
inspection {
id
url
severity
}
}
}
}
`
const getOptions = ({groupId}) => ({client, variables: {groupId}})
module.exports = graphql(compiledQuery, {options: getOptions})(InspectionFailure)It works fine if I change lines 7-8 to execute a query with the same return type. It will also make it past this error if I remove the client from the options (obviously at that point I'm initializing with the wrong client, so I can't actually execute the mutation in the child component).
Debugging in Chrome I found this suspicious code that checks if the client is different than the default and runs updateQuery(). I suspect the check for mutations on line 198 should have happened earlier, but I'm not entirely sure what the motivation is for that block of code.
Version
Intended outcome:
I want to show my users that the app is loading fresh data in the background when they get a render from the cache. (i.e. fetchPolicy
is set to cache-and-network
) In our app, this mostly happens when users navigate back to a page they've been on previously and we render the data from the cache first, while using cache-and-network
to load fresh data from the server.
Actual outcome:
I can't do that because networkStatus
does not expose that information.
Idea:
Rather than networkStatus
3 being specific to this.props.data.refetch()
, why not also set the networkStatus
to 3 when the data is refetched by the cache-and-network
fetch policy? The data is being refetched (even if not by calling refetch()
) so it makes sense for the networkStatus
to reflect that reality.
Awesome to get to start playing with this!
It would be great to be able to return promises from resolvers. My use case is a mutation to user login state, which calls an auth function returning a promise.
I believe this is the associated PR in graphql-anywhere
: https://github.com/apollographql/graphql-anywhere/pull/51
Intended outcome:
While server-side rendering, application is rendered including updated parent's state by resolved data from the child component that is wrapped with graphql
HOC.
Example:
<Parent>
{(updateParentState) => (
// This is component that is wrapped with graphql HOC
<Child updateParentState={updateParentState} />
)}
</Parent>
Actual outcome:
While server-side rendering, application is rendered but with initial parent's state, it looks like parent's state wasn't updated at all by the child component.
I'm using renderToStringWithData
on the server.
How to reproduce the issue:
It's just an example based on my application code. I found this issue while building a general pagination HOC for my application.
index.js
// <Pagination> doesn't know anything about graphql or fetching data
<Pagination>
{(updateTotalItems, renderPagination) => (
// Here <App> is wrapped with graphql() HOC
<App updateTotalItems={updateTotalItems} renderPagination={renderPagination} />
)}
</Pagination>
Pagination.js
class Pagination extends Component {
state = {
totalItems: 0,
};
// logic...
updateTotalItems = (totalItems) => {
this.setState({ totalItems });
};
renderPagination = () => {
const { totalItems } = this.state;
const totalPages = Math.ceil(totalItems / numberOfItemsPerPage);
// logic...
// calculate total pages based on totalItems and number of items per page etc.
// when everything is ready, just render component...
return <PaginationLinks page={page} totalPages={totalPages} ... />;
};
render() {
return this.props.children(
this.updateTotalItems,
this.renderPagination
);
}
}
App.js
class App extends Component {
static propTypes = {
updateTotalItems: PropTypes.func.isRequired,
renderPagination: PropTypes.func.isRequired,
};
// This is called on the server and it set up parent's state (<Pagination /> component)
componentWillMount() {
if (!this.props.data.loading) {
this.props.updateTotalItems(this.props.data.totalItems);
}
}
componentWillReceiveProps(nextProps) {
if (!nextProps.data.loading) {
this.props.updateTotalItems(nextProps.data.totalItems);
}
}
render() {
<div>
{/* render list of data... */}
{this.props.renderPagination()}
</div>
}
}
export default graphql(MyQuery)(App);
<Pagination>
state is correctly updated based on resolved data from the <App>
component and even pagination is rendered, but while calling renderToStringWithData
, it seems that application is rendered twice and during the 2nd render, <Pagination>
state is in initial state for all the time.// 1) Start rendering
renderToStringWithData is called
// 2) Looks like first render
App.componentWillMount() is called with resolved data
Pagination.updateTotalItems() is called with resolved data
Pagination state is updated
Pagination.renderPagination() is called and pagination links are rendered
// 3) Looks like second render
App.componentWillMount() is called with resolved data, AGAIN
Pagination.updateTotalItems() is called with resolved data
Pagination.renderPagination() is called with the initial state so links are not rendered because totalItems = 0 (state wasn't updated)
// 4) Return string representing application
HTML returned from renderToStringWithData doesn't contain pagination links...
Is this a bug? Has react-apollo some limitations in terms of server-side rendering .e.g. some things that works 100% correctly on the client-side, can stop working on the server-side like my example above?
Version
Intended outcome:
To access data.error
inside a graphQL
HoC wrapped component to do error handling.
Actual outcome:
The data.error
prop is never passed to the child as expected. I did a little digging and it appears that the logic to prevent unnecessary re-renders in the graphql
HoC doesn't take the error state into consideration and uses stale data props.
How to reproduce the issue:
I've updated your Apollo 2.0 Client example to illustrate the issue: https://codesandbox.io/s/pyp1zw702q
See the use of data.error
in list.js
. I console log when an error occurs using the apollo-link-error setup in index.js
Version
Intended outcome:
I have a React component wrapped with the graphql
function to get data from a GraphQL query.
The query is called on mounting, on this.props.data.refetch()
, or at some time if pollInterval
is set.
If any of these calls fails, I expect the component to be updated if a new call succeed, so that:
data.error
prop changes to undefined
and the component gets updated with the data received.pollInterval
is set and if at some point the network connection is lost, then when the connection is back the polling works as if the connection was never lost. So I want the polling to continue even if a poll has failed in the past and I want the component to be updated if new data is available (coming from a new poll of the same request or from the result of any other query or mutation in the app)Actual outcome:
After an error, data.error
remains defined and component never gets updated, even if data.refetch
is called or if pollInterval
is set.
My understanding:
Basically, when there is a network error, observers are unsubscribed. Thus any refetch only update Apollo store but does not trigger a rerender of the component.
I think it's the expected behaviour of the cleanupSubscription
call in https://github.com/apollographql/apollo-link/blob/master/packages/zen-observable-ts/src/zenObservable.ts
Which is called through obs.error(error)
in https://github.com/apollographql/apollo-client/blob/master/packages/apollo-client/src/core/ObservableQuery.ts
But I think react-apollo
should resubscribe to the query after an error to keep the component updated when new data arrive in the cache (after a data.refetch
, a poll, or any other query or mutation in the app).
Version
This is the issue asked here apollographql/apollo-client#1186 (comment)
Sometime I update store outside React by using writeQuery()
, I just try ApolloClient 2.0 everything fine except my component doesn't update after call writeQuery
Intended outcome:
Component props must update data after writeQuery
Actual outcome:
I take a screenshot of my console, in console after writeQuery
I call readQuery
on my sagas,
after that I log data in my container file from HOC and data from readQuery
How to reproduce the issue:
// container
graphql<{ profile: UserProfile }, {}>(Query, {
options: {
fetchPolicy: 'cache-and-network'
},
props: ({ data, ownProps }) => {
console.log('data from HOC', data.profile)
if (data.profile) {
console.log('data from readQuery', ownProps.client.readQuery({query: Query}).profile)
}
return ({ value: data.profile || { firstName: '', lastName: '' } })
}
})(FormComponent)
// saga file
profileQueryResult.profile[fieldName] = value
apolloClient.writeQuery({
query: Query,
data: {
...profileQueryResult
}
})
yield put({ type: 'form/updated' })
console.log(apolloClient.readQuery<{ profile: UserProfile }>({
query: Query
}).profile)
Version
Added a type generic to the graphql function named TGraphQLVariables.
It allows for specifying types that are required for the query that
should NOT be passed to the underlying component but are just used
for the GraphQL operation. The type is joined to the component's TProps
but not required on the passed in component.
Per apollographql/apollo-client#2198
This should not effect any current implementations as it defaults to {}
.
I need a sanity check on type inference in this case. I know that typescript does not currently do partial type inference, but I'm pretty sure that it will use default types when type inference is not possible. Someone might want to confirm that as it would be pretty unfortunate if someone were depending on type inference and this change somehow let their type unspecifyable (I don't know how that would occur, but would rather not cause someone an afternoon of type bugs).
There were some failing checks when I pulled the master branch. I took note of both the compile and test results before and after my changes and am including them here in case Travis complains.
Compile state prior to change:
jdstewar@LMC-056682 react-apollo (master) $ yarn compile
yarn run v1.1.0
$ tsc
$ npm run bundle
> [email protected] bundle /Users/jdstewar/gitRepo/react-apollo
> rollup -c && rollup -c rollup.browser.config.js && rollup -c rollup.test-utils.config.js
The following options have been renamed — please update your config: options.entry -> options.input, options.moduleName -> options.name, options.sourceMap -> options.sourcemap, options.dest -> options.output.file, options.format -> options.output.format
lib/index.js → lib/react-apollo.umd.js...
No name was provided for external module 'react' in options.globals – guessing 'React'
No name was provided for external module 'prop-types' in options.globals – guessing 'PropTypes'
No name was provided for external module 'redux' in options.globals – guessing 'redux'
No name was provided for external module 'apollo-client' in options.globals – guessing 'apolloClient'
No name was provided for external module 'graphql-tag' in options.globals – guessing 'graphqlTag'
No name was provided for external module 'react-dom/server' in options.globals – guessing 'ReactDOM'
created lib/react-apollo.umd.js in 119ms
The following options have been renamed — please update your config: options.entry -> options.input, options.moduleName -> options.name, options.sourceMap -> options.sourcemap, options.dest -> options.output.file, options.format -> options.output.format
lib/browser.js → lib/react-apollo.browser.umd.js...
No name was provided for external module 'react' in options.globals – guessing 'React'
No name was provided for external module 'prop-types' in options.globals – guessing 'PropTypes'
No name was provided for external module 'redux' in options.globals – guessing 'redux'
No name was provided for external module 'apollo-client' in options.globals – guessing 'apolloClient'
No name was provided for external module 'graphql-tag' in options.globals – guessing 'graphqlTag'
created lib/react-apollo.browser.umd.js in 101ms
The following options have been renamed — please update your config: options.entry -> options.input, options.moduleName -> options.name, options.sourceMap -> options.sourcemap, options.dest -> options.output.file, options.format -> options.output.format
lib/test-utils.js → lib/test-utils.js...
No name was provided for external module 'react' in options.globals – guessing 'React'
No name was provided for external module 'apollo-client' in options.globals – guessing 'ApolloClient'
No name was provided for external module 'graphql' in options.globals – guessing 'graphql'
No name was provided for external module 'prop-types' in options.globals – guessing 'PropTypes'
created lib/test-utils.js in 66ms
✨ Done in 2.62s.
Test state prior to change:
Summary of all failing tests
FAIL test/react-web/server/index.test.tsx
● SSR › `getDataFromTree` › shouldn't run queries if ssr is turned to off
expect(received).toEqual(expected)
Expected value to equal:
{}
Received:
undefined
Difference:
Comparing two different types of values. Expected object but received undefined.
at test/react-web/server/index.test.tsx:515:53
at tryCallOne (node_modules/promise/lib/core.js:37:12)
at node_modules/promise/lib/core.js:123:15
at flush (node_modules/asap/raw.js:50:29)
at _combinedTickCallback (internal/process/next_tick.js:131:7)
at process._tickCallback (internal/process/next_tick.js:180:9)
FAIL test/react-web/client/graphql/queries/index.test.tsx (6.582s)
● queries › stores the component name in the query metadata
Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
at pTimeout (node_modules/jest-jasmine2/build/queueRunner.js:53:21)
at ontimeout (timers.js:469:11)
at tryOnTimeout (timers.js:304:5)
at Timer.listOnTimeout (timers.js:264:5)
FAIL test/react-web/client/graphql/queries/loading.test.tsx (7.682s)
● [queries] loading › correctly sets loading state on remounted network-only query
Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
at pTimeout (node_modules/jest-jasmine2/build/queueRunner.js:53:21)
at ontimeout (timers.js:469:11)
at tryOnTimeout (timers.js:304:5)
at Timer.listOnTimeout (timers.js:264:5)
Test Suites: 3 failed, 24 passed, 27 total
Tests: 3 failed, 169 passed, 172 total
Snapshots: 1 passed, 1 total
Time: 10.333s
Ran all test suites.Compile after changes:
jdstewar@LMC-056682 react-apollo (master) $ yarn compile
yarn run v1.1.0
$ tsc
$ npm run bundle
> [email protected] bundle /Users/jdstewar/gitRepo/react-apollo
> rollup -c && rollup -c rollup.browser.config.js && rollup -c rollup.test-utils.config.js
The following options have been renamed — please update your config: options.entry -> options.input, options.moduleName -> options.name, options.sourceMap -> options.sourcemap, options.dest -> options.output.file, options.format -> options.output.format
lib/index.js → lib/react-apollo.umd.js...
No name was provided for external module 'react' in options.globals – guessing 'React'
No name was provided for external module 'prop-types' in options.globals – guessing 'PropTypes'
No name was provided for external module 'redux' in options.globals – guessing 'redux'
No name was provided for external module 'apollo-client' in options.globals – guessing 'apolloClient'
No name was provided for external module 'graphql-tag' in options.globals – guessing 'graphqlTag'
No name was provided for external module 'react-dom/server' in options.globals – guessing 'ReactDOM'
created lib/react-apollo.umd.js in 120ms
The following options have been renamed — please update your config: options.entry -> options.input, options.moduleName -> options.name, options.sourceMap -> options.sourcemap, options.dest -> options.output.file, options.format -> options.output.format
lib/browser.js → lib/react-apollo.browser.umd.js...
No name was provided for external module 'react' in options.globals – guessing 'React'
No name was provided for external module 'prop-types' in options.globals – guessing 'PropTypes'
No name was provided for external module 'redux' in options.globals – guessing 'redux'
No name was provided for external module 'apollo-client' in options.globals – guessing 'apolloClient'
No name was provided for external module 'graphql-tag' in options.globals – guessing 'graphqlTag'
created lib/react-apollo.browser.umd.js in 106ms
The following options have been renamed — please update your config: options.entry -> options.input, options.moduleName -> options.name, options.sourceMap -> options.sourcemap, options.dest -> options.output.file, options.format -> options.output.format
lib/test-utils.js → lib/test-utils.js...
No name was provided for external module 'react' in options.globals – guessing 'React'
No name was provided for external module 'apollo-client' in options.globals – guessing 'ApolloClient'
No name was provided for external module 'graphql' in options.globals – guessing 'graphql'
No name was provided for external module 'prop-types' in options.globals – guessing 'PropTypes'
created lib/test-utils.js in 66ms
✨ Done in 2.53s.
Tests after changes:
Summary of all failing tests
FAIL test/react-web/server/index.test.tsx
● SSR › `getDataFromTree` › shouldn't run queries if ssr is turned to off
expect(received).toEqual(expected)
Expected value to equal:
{}
Received:
undefined
Difference:
Comparing two different types of values. Expected object but received undefined.
at test/react-web/server/index.test.tsx:515:53
at tryCallOne (node_modules/promise/lib/core.js:37:12)
at node_modules/promise/lib/core.js:123:15
at flush (node_modules/asap/raw.js:50:29)
at _combinedTickCallback (internal/process/next_tick.js:131:7)
at process._tickCallback (internal/process/next_tick.js:180:9)
FAIL test/react-web/client/graphql/queries/index.test.tsx (6.166s)
● queries › stores the component name in the query metadata
Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
at pTimeout (node_modules/jest-jasmine2/build/queueRunner.js:53:21)
at ontimeout (timers.js:469:11)
at tryOnTimeout (timers.js:304:5)
at Timer.listOnTimeout (timers.js:264:5)
FAIL test/react-web/client/graphql/queries/loading.test.tsx (7.18s)
● [queries] loading › correctly sets loading state on remounted network-only query
Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
at pTimeout (node_modules/jest-jasmine2/build/queueRunner.js:53:21)
at ontimeout (timers.js:469:11)
at tryOnTimeout (timers.js:304:5)
at Timer.listOnTimeout (timers.js:264:5)
Test Suites: 3 failed, 24 passed, 27 total
Tests: 3 failed, 169 passed, 172 total
Snapshots: 1 passed, 1 total
Time: 9.054s
Ran all test suites.
Hey there. I have an npm module teselagen-react-components
that I share between repos. After upgrading my dependencies in TRC, my other projects depending on TRC started getting the following error:
It appears this line of compiled es6 code is failing:
import { gql } from "react-apollo";
export default gql(_templateObject);
When diving into my node_modules, I do indeed see that the gql export appears to be missing:
Any thoughts as to why this is happening?
Thanks!
I'm using the example from code here for SSR.
import { renderToStringWithData } from "react-apollo"
const client = new ApolloClient(....);
renderToStringWithData(app).then((content) => {
const initialState = client.getInitialState();
const html = <Html content={content} state={initialState} />;
res.status(200);
res.send(`<!doctype html>\n${ReactDOM.renderToStaticMarkup(html)}`);
res.end();
});
It works great, now all my components that have the `graphql` HOC will retrieve the data.
But, if I a query fails, the whole site will crash because of a single fail on a query.
Intended outcome:
If a query fails, I should be able to handle that error.
The site should continue working normally but without that piece of data.
Version
I have component which is used with react-router.
@graphql(PROFILE_CONTAINER_QUERY, {
options: ({ match: { params: { username } } }) => ({
variables: {
username,
},
}),
})
Everything works fine until I will click on back button in the browser.
I can see that my component is rerendered but I can see old data from previous page. Variable username has correct value but react-apollo is using old variable.
"apollo-cache-inmemory": "^0.2.0-beta.3",
"apollo-client": "^2.0.0-beta.3",
"apollo-fetch": "^0.6.0",
"apollo-link-batch-http": "^0.2.1-beta.6",
"apollo-link-http": "^0.6.1-beta.6",
"react-apollo": "^2.0.0-beta.0",`
I tried implementing apollo-link-state right after updating to apollo-client 2.
Seems like I am doing something wrong.
From the readme a lot seems clear. For a complete apollo-2-newbie this sentence here leaves a lot to the imagination though:
use the local link to create an Apollo Client instance
This raises some questions. For instance: Would this link be treated like:
Could you please provide an example for combining the local-state-link with the http link to create an Apollo Client instance?
Hey Apollo Team,
I've had a problem that I need to preload some data before doing main request to graphql server.
I've solved this by using custom logic, redux, redux-saga and config.skip. Still I have to sync redux-saga and redux on server and client so process is a bit challenging.
I think that this feature request
could improve dramatically handling scenarios and especially SSR when some data or any other async action is required before making the main request to graphql server.
Example
query Shops($location:Location) {
shops(location:$location) {
name
}
}
import React from 'react';
import { graphql } from 'react-apollo';
const App = ({ data }) => {
if (data.loading) {
return <div>Loading</div>;
}
if (data.error) {
return <div>error</div>;
}
return <div>{JSON.stringify(data.shops)}</div>;
};
const config = {
// Container component created by graphql(query, config)(Component)
// is in loading state until:
// - promise returned from async() resolves
// - and response from graphql returns
// [NEW API]
// you can name it as you want
asyncProps(props) {
const { id } = props.match.params; // just as example, react-router v4
// Mysterious API client
return Api.fetchLocationForShop({ id }).then((response) => {
// Here we return new props that will be merged with props component
return {
lat: response.data.location.lat,
lon: response.data.location.lon,
};
});
},
options(props) {
return {
variables: {
location: {
// Here we are using new props to setup query variable
lat: props.lat,
lon: props.lon,
};
},
};
},
};
export default graphql(ShopsQuery, config)(App);
What do you think about that approach? Is it possible to integrate such functionality into react-apollo? The main benefit would be super easy SSR.
Thanks in advance!
For lack of a better name 😉
All queries don't ever return results when a long operation is running (they don't even return results after said operation it's complete).
Please see wkh237/react-native-fetch-blob#563 for a bit more detail.
This issue has hit me recently, and I tried to come up with the best possible description of a problem, but please update it if you feel that it's misleading.
Intended outcome:
I'm trying to get object details through a client network interface. The schema I use is this:
import { makeExecutableSchema } from 'graphql-tools';
export const typeDefs = `
type Query {
currentThing: Thing!
}
type Thing {
id: String!
thingData: ThingData!
}
type ThingData {
foo: String!
bar: String!
}
`;
const resolvers = {
Query: {
currentThing: () => ({ id: 'dummy-id' }),
},
Thing: {
thingData: (thing) => {
return {
foo: `thing_foo-${thing.id}`,
bar: `thing_bar-${thing.id}`,
};
},
},
};
export const schema = makeExecutableSchema({ typeDefs, resolvers });
As you can see, my resolver returns all the properties of an object at once, but React Components query different properties of an object. The code is quite long, but here's a link to root component and sub components. As you can see, the properties of "Thing"
are queried at different times, which is controlled by a setTimeout
here. If I remove this setTimeout
When you run the app and wait for 3 seconds for the timeout to run, you'll see that the foo
property was resolved correctly, whereas the bar
one was not:
Actual outcome:
I found out that if I rename the object's id
property to something else - this behavior stops happening, see below for the "fix".
How to reproduce the issue:
Reproduction scenario is located here, the "fix" is described here.
Version
Using the withApollo
HOC I'm doing a query per below (the documentation suggests it's possible http://dev.apollodata.com/core/apollo-client-api.html#ApolloClient.query)
this.props.client.query({
query: doc,
reducer: someReducer,
variables: ...
});
I would expect someReducer
to be fired with arguments however that does not appear to be the case; it is not fired at all.
Intended outcome:
I have a HOC that reads some data from store:
compose(
withApollo,
withProps(({ client, subjectId }) => ({
name: get(
client.readFragment({
id: `Subject${subjectId}`,
fragment: SubjectFragment,
}),
'name'
),
}))
)I try to use `MockedProvider` to test the `readFragement` block. To do so I create a mocked redux store using `redux-mock-store`:
const mockStore = configureMockStore([])
const store = mockStore({
apollo: {
data: {
SubjectsomeId: {
id: 'someId',
name: 'test',
__typename: 'Subject',
},
},
},
})
then I create an ApolloClient like this (I'm using it in several other test so I assume that it works):
const client = new ApolloClient({
fragmentMatcher,
addTypename: true,
dataIdFromObject,
})
Then I stick this together:
const Component = () => <div />
const WrappedComponent = hoc(Component)
<MockedProvider client={client} store={store}>
<WrappedComponent />
</MockedProvider>
expect(component.find(Component).props('name').toBe('test')
Actual outcome:
The readFragment
call always return null
Version
I don't know if it is a choice: I had to install explicitly v. 1.4.16 to have Apollo 1.x instead of the new beta version.
Thank you,
Matteo
See this comment: apollographql/react-apollo#1232 (comment)
I noticed when using multiple clients, it's a pain on the server side to pass around client instances per request. This is managed with a single client b/c it's in the context.
A comment suggests to use it like so:
import MyOtherClient from "../other-client"
export default graphql(MyQuery, {
client: MyOtherClient,
})(MyComponent);
However, on the server, this is a lot harder. You'd have to have a container hoc that stores the extra clients and passes them down as a prop to the graphql wrapped component which seems kind of ugly.
What's a clean way to do this?
Can you please add the distribution to cdnjs.com similar to every other react libraries. For example https://cdnjs.cloudflare.com/ajax/libs/react-relay/0.10.0/relay.min.js. Thanks in advance.
This PR fixes #1324
Intended outcome:
In my React Native app, I attempted to make a GraphQL request without providing the necessary authorization information. Instead of getting an error indicating this, the only error message is "undefined". It would be massively helpful if the 401 Authorization error were showed to the developer.
I eventually figured out that it was a 401 causing havok by using Chrome Developer Tools:
How to reproduce the issue:
Attempt to make a GraphQL request against a GraphQL endpoint that requires auth, but don't include it.
Version
Intended outcome:
I have several graphql HOC's, some that have dependencies on the results of others. In one particular case, the query is stuck in a loading
state, even though the query has completed and the store updated.
Here is the query that is getting stuck.
const withServiceProvider = compose(
graphql(ServiceProviderQuery,
{
name: 'serviceProvider',
skip: ({account}) => !account || !account.serviceProvider,
options: ({account}) => ({
variables: {
id: account.serviceProvider && account.serviceProvider.id
}
}),
props: ({ serviceProvider }) => {
const props = {
serviceProvider: {
...flattenGraphQLProps('serviceProvider', serviceProvider)
}
}
const sp = path(['serviceProvider'], serviceProvider)
if (!sp) return props
return {
serviceProvider: {
...props.serviceProvider,
viewId: spViewId(sp)
}
}
}
}
),
setPropTypes({
serviceProvider: PropTypes.object
})
)
Here is the Component that is using it:
const ServiceProviderContainer = (props: Object): React$Component => {
const { l10n, serviceProvider } = props
return (
<div id='service-provider-container'>
<Header />
{
serviceProvider.loading ?
<Loader />
:
serviceProvider.error ?
<NotFound message={l10n.localise('sp-not-found', 'This service provider does not exist.')} />
:
<Route path='/service-provider/:id/:module?'>
<ServiceProvider {...props} />
</Route>
}
</div>
)
}
I am composing the component with withServiceProvider
in the same way I am doing with all my other components that use HOCs.
export default compose(
withl10n('service-provider', resourceIds),
withAccount,
withServiceProvider,
...
)(ServiceProviderContainer)
Now, all is great...the loader shows, the query is executed and the results are serialized into the store,
and normally the component will receive the result. However...
Actual outcome:
As you can see below, the component is not getting the final result, and loading
is never cleared.
Notes
props
is never called with a completed serviceProvider
(i.e. data
). It is called twice, each time with the same, as follows:Version
Hi guys.
I've been doing some looking through the docs but the closest thing I could find to an answer was to use apollo-link, I will get to that in a sec.
I've been working on adding Apollo GraphQL to my companies Wordpress API Proxy so that we use GraphQL as the transport between the WP Proxy to the React Client, I've hit a little issue though. After reading what feels like almost all of the docs I cannot find a way to manually insert a record into the cache store (except in mutations).
I need to be able to do this because the way we build pages is via the following data structure:
individual page -> Components inside of page
So when the user navigates the page x, my query fetches all of the generic page data aswell as the list of components and their data. Then the components are mounted in my react front end aannnd If the component has to fetch data from the server to power itself (say a form) the page has to wait for this query to complete. This is a real bummer for me because we use SSR, so the page loads instantly how it should look, except my form shows loading!
What I was going to try and do was on the server, when I get back the list of components that the page will display, look at the Component and find whatever queries it will run and the args for em and then fetch the data on the server!
The data would then be attached to a Prefetch type on the Page's query, and the client would deserialise the prefetched data and insert it into the store!
The only two ideas i've had to do this are to use mutations for the page or look further into the new apollo-link.
Using mutations:
To do it this way I would simply send a mutation including the page I want as the request, and then return the default page data in the result of this mutation and use the update function that mutate gets to insert my prefetched data! But this sucks because why am I mutating a page request!
apollo-link:
Tis friday and my ability to better asses the viability of apollo-link as a good solution is limmited. But if I could find a way to use link to make a stock standard apollo client, but inject some code like express middleware to search all queries for any which return PreFetch data and auto-magically update the store somhow.. This feels like (if once again my mush brain understands why apollo-link was made) a really good solution. Maybe instead of using the apollo in-built cache it will have a seperate cache for pre-fetch and I will stop the request for data if I notice I have the data prefetched??
OR
Why can't my queries have access to the update functionality that mutate has? That way I could manually update my store without having to use mutations!
Thanks for reading if you made it this far. I have re-read this to make sure it makes atleast 1% sense, however I am rather smashed from this week so I wouldn't be supprised if it's hard to read. If that's the case please leave some questions about my question and I will get back to you in Aussie hours!
Cheers,
Michael.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.