Intended outcome:
<TextInput>Done
Actual outcome:
You usually set the value for
I tried some rather "dirty" workarounds like this to get things from the query component into state...
setData (data) {
if(this.state.loading) {
this.setState({
text: data.text,
loading: false
});
}
};
onCompleted={this.setData.bind(this)}
Apart from feeling clunky it comes with the side-effect of seeing the data when fetched from remote, so not taking advantage of the locally cached data.
I read some folks where trying to "simply" manipulate the data in Apollo's cache whenever the user changes something. That's not really what I want tho, as I want to dismiss every changes the user made should she decide to dismiss things.
Version
I could be wrong here, but the entire thought process behind gql is that you retrieve the data as you want it from the database. so you option 2. shouldnt be done.
That said in my project I reverted to HOCs so i could set it to state because I come from REST Apis and was going grey very quickly figuring it all out haha
I know it seems like an anti-pattern given how you have to now setState in the render but this tweet by Peggy really helped me understand the whole thought process:
https://twitter.com/peggyrayzis/status/1050483882208964611
She then goes on to say HOCs are supported so perhaps they arent completely against us using them, im happy to help out with setting them up for you if you decide to go that route
Thanks @builtbyproxy. 2. is about allowing user to edit the existing data, not about how I want to retrieve the data, or did you mean the workarounds mentioned?
I'll likely also go back to HOCs as well, but it feels weird that nobody really thought about this. I couldn't find a single react native example that uses
Ah I meant editing the existing data but like you said its not really documented well. It seems like they almost want us to refetch the data from the DB as the user edits what they want.
So rather then retrieve it all and then filter/sort, they would requery as they edit.... Could you perhaps retrieve it all and then write it to local cache?
Either way it seems like an anti-pattern or overkill on network requests to get the same data constantly.
If you find a good example for react-native to fetch and store the data that would be awesome @sreuter. My understanding is you use fetchPolicy: "cache-only" queries to save the data to the local cache, but im not entirely sure.
I want the user to change the data that has been fetched, not which data is going to be fetched. Think about a simple screen, which shows existing data that has been fetched :) I want the user to be able to edit the data, then save it. Because of how ReactNative's
I understand but I dont believe thats the intended use of GraphQL with Apollo's Query and Mutation components
For something like that you would have to use HOCs
I think the key thing to recognise here is that there are actually two pieces of state in the world - the value that's been saved on the server (in apollo cache), and the value that will be saved if you hit submit (in local state). Your app needs to know about both and track them separately. So you're not _really_ changing the data that was fetched until you hit save.
So - perhaps the thing you need to do here is have the query results passed into your stateful component as initialValues props (by Query), and _also_ keep track of currentValues for "dirty" fields in local state (starts null,). Then the display value is a combination of the two: dirtyValue["field"] || initialValue["field"] and your onChangeText function just updates those dirtyValues.
I've recently been making use of Formik, which does a great job of this pattern. If you take those values from the query and pass them in as initialValues to a Formik component, then you can still override in your Fields. Then in the onSubmit function you take the values form Formik and pass them back to your mutation.
Check this out https://jaredpalmer.com/formik/docs/guides/react-native
BTW I don't think this is really specific to ReactNative, you'd have the same issue on a controlled HTML input component.
@amcvitty That makes a lot of sense, I'll give this a try tonite! I believe my expectation was Apollo taking care of these common concerns, but maybe that can be achieved through some additional augmentation of their components at some point.
@amcvitty Following your advice I've implemented this myself + tried formik... both implementations work as expected. Thank you!
Most helpful comment
I think the key thing to recognise here is that there are actually two pieces of state in the world - the value that's been saved on the server (in apollo cache), and the value that will be saved if you hit submit (in local state). Your app needs to know about both and track them separately. So you're not _really_ changing the data that was fetched until you hit save.
So - perhaps the thing you need to do here is have the query results passed into your stateful component as initialValues props (by Query), and _also_ keep track of currentValues for "dirty" fields in local state (starts null,). Then the display value is a combination of the two:
dirtyValue["field"] || initialValue["field"]and your onChangeText function just updates those dirtyValues.I've recently been making use of Formik, which does a great job of this pattern. If you take those values from the query and pass them in as initialValues to a Formik component, then you can still override in your Fields. Then in the onSubmit function you take the values form Formik and pass them back to your mutation.
Check this out https://jaredpalmer.com/formik/docs/guides/react-native
BTW I don't think this is really specific to ReactNative, you'd have the same issue on a controlled HTML input component.