Open MichelDiz opened 6 years ago
I don't have much experience with those. I would LOVE someone to submit one.
btw I have final-form working with apollo-client Graphql, its simple enough to do. Ill see if I can get to creating it.
Hi @kavink - interesting, thanks. Did you have time to work on this and if so, would you mind sharing a quick gist for this please?
I have a really basic example with apollo:
const query = gql`{ item { id, field1, field2 } }`;
const FormWithData = graphql(query, {
props: ({ data }) => ({
initialValues: data.item,
}),
})(Form);
Now FormWithData
will be populated with the response from GraphQL. Then to save you can do:
const onSubmit = (variables) => client.mutate({
mutation: gql`
mutate($id: ID, $field1: String, $field2: String) {
submitItem(id: $id, field1: $field1, field2: $field2) {
id, field1, field2
}
},
`,
variables,
}).then(() => null) // no error
I'm running into a problem with this approach though. When you save data, the response will update apollo's cache, which will update initialValues
. Therefore, anything you've changed between submitting and the response coming back will be overwritten with apollo's new cache (the data as it was when you submitted).
I sort of fixed the issue with mutations by using optimisticResponse
. It's still a race condition, but it should resolve pretty instantly, and it seems unlikely that a user will be able to type anything in another field after saving - maybe it would be an issue if you're saving on every keystroke.
const onSubmit = (variables) => client.mutate({
mutation, // same as before
variables,
optimisticResponse: {
submitItem: {
__typename: 'Item',
...variables
},
},
});
@kavink is this a similar approach to what you did? I'm curious if there's a better way to handle this. It feels sort of hacky to me to have to use optimisticResponse
and just hope that nobody types anything before the cache updates.
@redbmk I am not sure if I understood the questions, but look at this https://codesandbox.io/s/xr0mvl1904
You just need to replace save with mutations and load with query.. And reformat the load and save as the form needs it.
Ah, yeah that does the trick. The problem I was running into was mapping initialValues
directly to the graphql hoc, which updates on every change. This example actually updates initialValues
again after the save, but I'm not sure that's really necessary.
I suppose potentially values
-> preSaveValues
-> postLoadValues
might not be the same as values
, but if you're not using those then probably no real point in updating initialValues
.
The main difference for me is I'm trying to save each field on blur, so disabling the whole form doesn't make as much sense in this case. Instead of using the hoc, a simple graphql.query
would work well for the load
command, and then the optimisticResponse
shouldn't be necessary.
I came back to this form. I want to put an example in the snack.expo.io using Apollo-boost and the new Apollo mutation.
Perhaps some of you have not understood my question in the beginning. Expo is a React-Native pkg (can be used for web too - universal app). Some examples you guys show up had Divs and other components that do not exist in React-Native for env. Not a big deal anyway.
I believe that a part of that question is settled. Only issue with Expo that does not. I've been testing the possibility a few hours ago, using the example forms and most of the solutions above.
In the issue https://github.com/final-form/react-final-form/issues/212 the user soosap comes the approach of a (proof of) concept for Expo. But I still have not been able to emulate his solution perfectly. I think his example is for the web itself. I did not understand if he was doing it for React-Native. And I do not want to go straight into the approach with Apollo Consumer or even the old HOC. Because Apollo's new approaches are much clearer and easier to deal with later.
Here below is a template that I was able to render on a mutation. Just render, I've isolated the mutation function only to see if I can manipulate the generated values. Then deal with the values for GraphQL variables later on.
In the model I could not get the values. Something wrong is doing or missing. Without being sure that the values will pass, there is no success. If I can get the values in flight, I can send them to the mutation through variables. But I can not, as I have already explained.
I'm using Typescript by the way.
"devDependencies": {
"@types/expo": "^25.0.3",
(...),
"@types/react-native": "^0.52.22",
}
"dependencies": {
(...),
"apollo-boost": "^0.1.4",
"expo": "^26.0.0",
"final-form": "^4.5.2",
"react": "^16.3.0-alpha.1",
"react-final-form": "^3.3.1",
"react-native": "https://github.com/expo/react-native/archive/sdk-26.0.0.tar.gz",
}
import * as React from "react";
import Settings from "../../stories/screensProtected/Settings";
import { View, Text, TouchableOpacity, TextInput, StyleSheet } from "react-native";
import { Form as FinalForm, Field, FormRenderProps } from "react-final-form";
import "final-form";
import REGISTER_USER from "../../../graphql/mutations/signup";
import { /*Query,*/ Mutation } from "react-apollo";
- The handleSubmit is fired and I see the Alert happen. But it is empty.
const handleSubmiter = (values) => {
alert(JSON.stringify(values, 0, 2));
};
const formulario = (
<React.Fragment>
<Text style={{color: "red"}}>Test Tittle</Text>
<Mutation mutation={REGISTER_USER} variables={{ id: "imageId" }}> //fake variables
{mutate => (
<FinalForm
onSubmit={onSubmit}
render={({ handleSubmit, values }: FormRenderProps) => (
<View>
<Text style={{ fontSize: 16, fontWeight: "bold" }}>Label:</Text>
<Field
component={() => (
<TextInput
placeholder={"$00.00"}
keyboardType="numeric"
style={styles.textInput}
/>
)}
/>
<TouchableOpacity
style={{ height: 55, marginTop: 15, backgroundColor: "#005abc", justifyContent: "center", alignItems: "center" }}
onPress={() => handleSubmiter(values)}
>
<Text style={{ color: "#fff" }}>Submit</Text>
</TouchableOpacity>
</View>
)}
/> )
}
</Mutation>
</React.Fragment>
);
it could be like that too
const formulario2 = (
<Mutation mutation={REGISTER_USER}
onCompleted={result => {
console.log("result", result);
}}
>
{(mutate, { loading, error, data }) => {
let registreNow = ( values ) => {
const { username, pass, email } = values;
const variables = {
username : username,
password : pass,
email : email,
};
setTimeout(() => {
mutate({ variables: { input: variables } });
});
}
};
return (
<React.Fragment>
// I deleted some fields so It did not get huge.
<FinalForm => (
// I deleted some fields so It did not get huge.
<Field/>)
<TouchableOpacity
// I deleted some fields so It did not get huge.
onPress={() => registreNow(values)}
>
<Text style={{ color: "#fff" }}>Submit</Text>
</TouchableOpacity>
)}
/>
{ error ? error : null}
{ data ? data : null}
</React.Fragment>
);
}}
</Mutation>
);
Are you submitting a bug report or a feature request?
example request