【问题标题】:How to use useMutation hook in withFormik() form如何在 withFormik() 形式中使用 useMutation 钩子
【发布时间】:2020-08-22 02:19:57
【问题描述】:

此 Formk 表单工作正常,但是当我在表单中使用“useMutation”挂钩时,它显示错误“在上下文中找不到“客户端”或作为选项传入。将根组件包装在 中,或通过通过选项中的 ApolloClient 实例”。我也使用了“突变”,它给出了同样的错误。我认为错误在突变部分。

form.js

import React,{useState} from "react"
import {render} from "react-dom"
import {withFormik, Form, Field} from 'formik'
import * as Yup from "yup"
import { useMutation } from '@apollo/react-hooks';
import gql from 'graphql-tag'

const REGISTER_MUTATION=gql`
mutation ($email: String!, $password: String!, $username: String!)
{createUser(
  email: $email, username: $username, password: $password){
  user{username, email}}
}`;

const App = ({values, errors, touched, isSubmitting })=> {

// Here is the problem, if i remove this portion it works fine
    const [username, setUsername]= useState("username");
    const [email, setEmail]= useState("email");
    const [password, setPassword]= useState("password");

    const [createUser] = useMutation(REGISTER_MUTATION)
        async function createNewUser() {
         await createUser({ variables: { username , email , password },
            })
        }; console.log(createUser);
//Afterwards it works fine
return(

  <Form>
    <div>
       {touched.email && errors.email && <p>Invalid Email </p>}
    <Field type="email" name="email" placeholder="Email" />
    </div>
    <div>
    {touched.password && errors.password && <p>Invalid password </p>}
    <Field type="password" name="password" placeholder="Password" />
    </div>
    <label>
    <Field type="checkbox" name="newsletter" checked={values.newsletter}/>
    Ok got it
    </label>

    <Field component="select" name="plan">
      <option value="value">Free</option>
      <option value= "premium" > Premium</option>
    </Field>
    <button type="button" disabled={isSubmitting}>Submit</button>
  </Form>
);}

const FormikApp = withFormik({
  mapPropsToValues ({email, password, newsletter, plan}){
    return{
      password: password || " ",
      email: email || " ",
      newsletter: newsletter || true,
      plan : plan || 'Premium'
    }
  },
validationSchema: Yup.object().shape({

    email: Yup.string().email("Invalid email account").required("field missing"),
    password: Yup.string().email().min(8,"password is weak").required()
  }),

  handleSubmit(values, setSubmitting){
    setTimeout(()=>{
    setSubmitting(false)
  },2000)
  }
})(App)

render(<FormikApp  />,  document.getElementById("root"))
export default FormikApp

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import * as serviceWorker from './serviceWorker';
import  FormikApp from'./component/form1';
import ApolloClient from 'apollo-boost';
import { ApolloProvider } from 'react-apollo';
import { ApolloProvider as ApolloProviderHooks } from '@apollo/react-hooks';

const client = new ApolloClient({ uri: 'http://127.0.0.1:8000/graphql/' });
const App = () => (

   <ApolloProvider client={client}>
<ApolloProviderHooks client={client}>
    <FormikApp />
</ApolloProviderHooks>
   </ApolloProvider>
);

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

serviceWorker.unregister();

pakage.json

{
  "name": "start_react",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@apollo/react-hooks": "^3.1.5",
    "@emotion/core": "^10.0.28",
    "@emotion/styled": "^10.0.27",
    "@material-ui/icons": "^4.9.1",
    "@testing-library/jest-dom": "^4.2.4",
    "@testing-library/react": "^9.5.0",
    "@testing-library/user-event": "^7.2.1",
    "apollo-boost": "^0.4.7",
    "cors": "^2.8.5",
    "express": "^4.17.1",
    "formik": "^2.1.4",
    "graphql": "^15.0.0",
    "graphql-tag": "^2.10.3",
    "react": "^16.13.1",
    "react-apollo": "^3.1.5",
    "react-apollo-hooks": "^0.5.0",
    "react-dom": "^16.13.1",
    "react-scripts": "3.4.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

【问题讨论】:

  • handleSubmit中调用createUser(在变量中传递值)
  • 我试过这个handleSubmit(values, {setSubmitting}, createUser){ setTimeout(()=&gt;{ setSubmitting(false) },2000) createUser({ variables: { ...values, email : ${values.email} ,密码:${values.password} ,用户名:${values.username}` }}); console.log(values)}` 并得到错误 TypeError: createUser is not a function at Object.handleSubmit
  • createUser 已在组件 [global] 范围内定义,您无需将其定义为 handleSubmit 参数
  • 现在错误“第 149:6 行:'createUser' 未定义 no-undef”
  • hmmm...withFormik,因为 HOC 在外面...将其转换为useFormik,在useMutation 之后声明? ...或将 放置在带有“useMutation”的某些功能组件中 ...将突变移到外部 .... const MutationWithFormik = () =&gt; { const [createUser] = useMutation(REGISTER_MUTATION); return &lt;FormikApp createUser /&gt;;} ...在handleSubmit中使用props.createUser ...当然渲染MutationWithFormik作为主要

标签: reactjs graphql react-hooks apollo-client formik


【解决方案1】:

在你的form.js 中不要这样做render(&lt;FormikApp /&gt;, document.getElementById("root"))

您正在渲染&lt;FormikApp /&gt;,如您所见,您需要使用ApolloProvider 包装&lt;FormikApp /&gt;,因为useMutation 需要apollo 客户端。

如果您删除render(&lt;FormikApp /&gt;, document.getElementById("root")),我相信您的问题不会持续存在

编辑

工作示例:https://codesandbox.io/s/awesome-ishizaka-kuhxi

您可以为您的FormikApp 制作一个包装器。像这样的:

import React from "react";
import { withFormik, Form, Field } from "formik";
import * as Yup from "yup";
import { useMutation } from "@apollo/react-hooks";
import gql from "graphql-tag";

const REGISTER_MUTATION = gql`
  mutation($email: String!, $password: String!, $username: String!) {
    createUser(email: $email, username: $username, password: $password) {
      user {
        username
        email
      }
    }
  }
`;

const App = ({ values, errors, touched, isSubmitting }) => {
  //Afterwards it works fine
  return (
    <Form>
      <div>
        {touched.email && errors.email && <p>Invalid Email </p>}
        <Field type="email" name="email" placeholder="Email" />
      </div>
      <div>
        {touched.password && errors.password && <p>Invalid password </p>}
        <Field type="password" name="password" placeholder="Password" />
      </div>
      <label>
        <Field type="checkbox" name="newsletter" checked={values.newsletter} />
        Ok got it
      </label>

      <Field component="select" name="plan">
        <option value="value">Free</option>
        <option value="premium"> Premium</option>
      </Field>
      <button type="submit" disabled={isSubmitting}>
        Submit
      </button>
    </Form>
  );
};

const FormikApp = withFormik({
  mapPropsToValues({ email, password, newsletter, plan }) {
    return {
      password: password || " ",
      email: email || " ",
      newsletter: newsletter || true,
      plan: plan || "Premium"
    };
  },
  validationSchema: Yup.object().shape({
    email: Yup.string()
      .email("Invalid email account")
      .required("field missing"),
    password: Yup.string()
      .email()
      .min(8, "password is weak")
      .required()
  }),

  handleSubmit(values, { props }) {
    props.createUser({
      variables: values
    });
  }
})(App);

const FormikWrapper = () => {
  const [createUser] = useMutation(REGISTER_MUTATION);
  return <FormikApp createUser={createUser} />;
};

export default FormikWrapper;

【讨论】:

  • useMutation 仍然不能与Formik一起工作,任何建议
  • 您能详细说明一下吗?什么不工作?什么错误?
  • 我想用这个 useMutation 代码 sn-p 来改变值,但它根本不起作用,你能写下我将如何在这个表单上下文中改变值吗?谢谢
  • @saud00 如果我正确理解您的问题,您是在问如何在withFormikhandleSubmit 中调用突变?
  • 是的,如何调用withFormikhandleSubmit中的突变?使用 useMutation 钩子。
猜你喜欢
  • 2020-04-27
  • 1970-01-01
  • 2021-09-17
  • 2021-04-04
  • 2023-04-10
  • 1970-01-01
  • 2018-12-12
  • 2022-10-13
  • 2021-03-21
相关资源
最近更新 更多