【问题标题】:how to submit a formik form through mutation with ApolloClient?如何通过 ApolloClient 的变异提交 formik 表单?
【发布时间】:2019-02-25 13:57:14
【问题描述】:

我已经使用 antd 创建了一个示例 Formik 表单。现在我正在使用 POST_MUTATION 添加突变。如何通过 formik 提交表单值。这里我在表单中调用了handleSubmit。但是它没有被调用?

 import React from 'react'
import { Formik, Field, Form } from 'formik';
import * as AntD from "antd";
import TextField from "./shared/TextField"
import { Mutation, graphql } from 'react-apollo'
import gql from 'graphql-tag'
import data from './shared/data'

const POST_MUTATION = gql`
  mutation PostMutation($username: String!, $email: String!, $password: String!){
    post(username: $username, email: $email, password: $password) {

      username
      email
      password
    }
  }
`


class FormikApollo extends React.Component {
  state = {
      username: '',
      email: '',
      password: '',
      data: {}
  }

  handleChange= (e) => {
        this.setState({
            [e.target.name] : e.target.value,
            data
        })
  }

  handleSubmit = () => {
   alert("called")
  }

我使用这种方式添加我的formik表单。现在我想提交这些未提交的表单值。如何在formik中提交表单值?

form = props => {
            const { username, email, password  } = this.state;
            return (
                <div align="center">
                    <h3 align="center">Registration Form</h3>
                    <Mutation mutation={POST_MUTATION} variables={{ username, email, password }}>
                    { postMutation  => (
                    <Form onSubmit={(formikValues) => postMutation({ variables: formikValues })}>
                        <Row gutter={4}>
                            <Col span={12} push={5}>
                                <Field
                                    name="username"
                                    label="Name"
                                    placeholder="Enter a Name"
                                    component={TextField}
                                    formitemlayout={formItemLayout} 
                                    value={this.state.username}
                                    onChange={this.handleChange}
                                    />

                                <Field
                                    name="email"
                                    label="Email"
                                    placeholder="Enter an Email"
                                    component={TextField}
                                    formitemlayout={formItemLayout} 
                                    value={this.state.email}
                                    onChange={this.handleChange}
                                    />

                                <Field
                                    name="password"
                                    label="Password"
                                    type="password"
                                    placeholder="Enter a Password"
                                    component={TextField}
                                    formitemlayout={formItemLayout} 
                                    value={this.state.password}
                                    onChange={this.handleChange}
                                  />


                                 <Button type="submit" onClick={JSON.stringify(postMutation)}>Submit</Button>


                            </Col>
                        </Row>
                    </Form>
                    )}

                    </Mutation>
                </div>
            )
        }


        render() {

            return (
                <div align="center">
                    <Formik
                        initialValues = {{
                          username: '',
                          email:'',
                          password:''
                        }}
                        render={this.form}
                    />

                </div>
            )
        }

    }

    export default FormikApollo

【问题讨论】:

    标签: reactjs gatsby antd apollo-client formik


    【解决方案1】:

    你的方法是正确的。最好将整个组件包装成突变并使用它来渲染道具。 这是一个简单的寄存器组件。如果您发现某些语法难以理解,我会使用 typescript。

    ant-design 和 graphql(Typescript) 的工作示例:https://github.com/benawad/graphql-typescript-stripe-example

    Youtube 系列:https://www.youtube.com/watch?v=G-Kj8Re6spA&amp;list=PLN3n1USn4xllF5t1GZhEwFQNDnStgupdB

    import { Field, Formik } from "formik";
    import React from "react";
    import Layout from "../components/Layout";
    
    import { RegisterMutationVariables, RegisterMutation } from "../../schemaTypes";
    
    const registerMutation = gql`
      mutation RegisterMutation($email: String!, $password: String!) {
        register(email: $email, password: $password)
      }
    `;
    
    export default () => {
      return (
        <Layout title="Register page">
          <Mutation<RegisterMutation, RegisterMutationVariables>
            mutation={registerMutation}
          >
            {register => (
              <Formik
                validateOnBlur={false}
                validateOnChange={false}
                onSubmit={async (data, { setErrors }) => {
                  try {
                    const response = await register({
                      variables: {
                        data
                      }
                    });
                    console.log(response);
                  } catch (err) {
                    console.log(err)
                  }
                }}
                initialValues={{
                  email: "",
                  password: ""
                }}
              >
                {({ handleSubmit }) => (
                  <form onSubmit={handleSubmit}>
                    <Field
                      name="email"
                      placeholder="email"
                      component={InputField}
                    />
                    <Field
                      name="password"
                      placeholder="password"
                      type="password"
                      component={InputField}
                    />
                    <button type="submit">submit</button>
                  </form>
                )}
              </Formik>
            )}
          </Mutation>
        </Layout>
      );
    };
    

    【讨论】:

      【解决方案2】:

      好吧,代码格式使您很难看到您的代码,但是,通常您可以将表单放入突变中,并将突变函数用作表单的提交函数,如下所示:

      <Form onSubmit={(formikValues) => postMutation({ variables: formikValues })}>
      

      【讨论】:

      • 我尝试在突变中调用表单,也调用了 onSubmit={(formikValues) => postMutation({ variables: formikValues })} 但未提交表单
      • 您介意用您使用的代码更新您的帖子吗?
      • 代码对我来说似乎很好。我认为您应该设置一个沙箱。 codesandbox.io
      • 但是antd在沙盒代码中并没有应用到formik表单但是我原来的表单是应用到antd的
      【解决方案3】:

      我采用了一种不同的方法,同时使用了 formikapollo mutation。 我没有使用另一个 Mutation 标签(顺便说一句,让你的代码看起来很脏),而不是使用 this.props.mutate() 在一个函数中。

      当您在 graphql 的影响下导出具有该突变的组件时,可以在 props 中找到您的突变。一会儿你会看到的。

      这就是我的表单在组件的主 render() 函数中的样子

      < Formik
      initialValues = {
        {
          title: '',
        }
      }
      onSubmit = {
        this.submitMutation // my own function
      }
      render = {
        this.renderForm // my own function that just returns views and texts tags
      }
      validationSchema = {
          Yup.object().shape({
            title: Yup
              .string()
              .required('title is required'),
          })
        } >
      
        <
        /Formik>

      下面是formik调用的提交变异函数

      submitMutation = () => {
        return this.props.mutate({
          variables: {
            title: this.state.title,
          },
        })
      }
      最后做这个

      export default graphql(addBillMutation)(CreateBill);

      OverAll Code..请根据您的西装调整它

      import React from 'react';
      import {
          StyleSheet, Text, Image, View, TextInput, Picker, TouchableOpacity, ScrollView, KeyboardAvoidingView
      } from 'react-native';
      
      import Header from './header';
      import { graphql } from 'react-apollo';
      //import mutation query from queries
      import { getBillsQuery, addBillMutation } from './queries/queries';
      import { Formik } from 'formik';
      import * as Yup from 'yup';
      
      class CreateBill extends React.Component<any, any>  {
          constructor(props: any) {
              super(props);
              this.state = {
                  title: "",
                  loading: false,
              }
              this.submitMutation = this.submitMutation.bind(this);
          }
      
          submitMutation = () => {
              return this.props.mutate({
                  variables: {
                      title: this.state.title,
                  }
              })
          }
      
          _handleSubmit = async (values: any) => {
              //setting values here, when form is already validated by yup in formika
              this.setState({
                  title: values.title,
              });
              try {
                  //set loading to true before sending request
                  this.setState({ loading: true });
                  await this.submitMutation()
                      .then(({ data }) => {
                        //response handling
                      }).catch((error) => {
                          this.setState({ loading: false });
                          //error handling
                      });
              } catch (error) {
                  //handle error
              }
          }
      
          renderForm = (formikProps: any) => {
              const {
                  values, handleSubmit, handleBlur, handleChange, errors,
                  touched, isValid, isSubmitting
              } = formikProps;
      
              return (
      
                      <ScrollView>
                                  <View>
                                              <TextInput
                                                  style={styles.input}
                                                  value={values.title}
                                                  placeholder="title goes here"
                                                  onChangeText={handleChange('title')}
                                                  onBlur={handleBlur('title')}
                                              />
                                          </View>
                                              {(touched.title && errors.title) ? touched.title && errors.title : "Required"}
                                          </Text>
                                      </View>
                                              
                                  </View>
                      </ScrollView>
              );
          }
          render() {
              return (
                  <View>
                      <Header />
                      <View>
      
                          <Formik
                              initialValues={{ title: ''}}
                              onSubmit={this._handleSubmit}
                              render={this.renderForm}
                              validationSchema={Yup.object().shape({
                                  title: Yup
                                      .string()
                                      .required('title is required'),
                              })}
                          >
      
                          </Formik>
                      </View>
                  </View>
              );
          }
      }
      
      export default graphql(addBillMutation)(CreateBill);

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-09-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多