如何在 withFormik() 形式中使用 useMutation 钩子
Posted
技术标签:
【中文标题】如何在 withFormik() 形式中使用 useMutation 钩子【英文标题】:How to use useMutation hook in withFormik() form 【发布时间】: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)
userusername, 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(()=> 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
之后声明? ...或将 const MutationWithFormik = () => const [createUser] = useMutation(REGISTER_MUTATION); return <FormikApp createUser />;
...在handleSubmit
中使用props.createUser
...当然渲染MutationWithFormik
作为主要
【参考方案1】:
在你的form.js
中不要这样做render(<FormikApp />, document.getElementById("root"))
您正在渲染<FormikApp />
,如您所见,您需要使用ApolloProvider
包装<FormikApp />
,因为useMutation
需要apollo 客户端。
如果您删除render(<FormikApp />, 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 如果我正确理解您的问题,您是在问如何在withFormik
的handleSubmit
中调用突变?
是的,如何调用withFormik的handleSubmit中的突变?使用 useMutation 钩子。以上是关于如何在 withFormik() 形式中使用 useMutation 钩子的主要内容,如果未能解决你的问题,请参考以下文章
如何下载(或以 blob 形式获取)用于流式传输 HTML5 视频的 MediaSource?
(123456789).toLocaleString('en-US')