Как использовать хук useMutation в форме withFormik () - PullRequest
1 голос
/ 07 мая 2020

Эта форма Formk работает нормально, но когда я использую ловушку «useMutation» в форме, она показывает мне ошибку «Не удалось найти« клиент »в контексте или передано в качестве опции. Оберните компонент root в или передать экземпляр ApolloClient через параметры ". Я также использовал «Мутацию», которая дает ту же ошибку. Я думаю, что ошибка связана с мутацией.

форма. 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

индекс. 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();

упаковка. 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"
    ]
  }
}

1 Ответ

0 голосов
/ 07 мая 2020

В вашем form.js не делайте этого render(<FormikApp />, document.getElementById("root"))

Вы визуализируете <FormikApp /> и, как видите, вам нужно обернуть <FormikApp />, используя ApolloProvider, потому что 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;
...