4
votes

This Formk form is working fine but when i use "useMutation" hook in form, it shows me Error "Could not find "client" in the context or passed in as an option. Wrap the root component in an , or pass an ApolloClient instance in via options". I used "Mutation" as well that gives same error. I think error is in mutation portion.

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"
    ]
  }
}
1
invoke createUser (passing values in variables) in handleSubmitxadm
I tried this handleSubmit(values, {setSubmitting}, createUser){ setTimeout(()=>{ setSubmitting(false) },2000) createUser({ variables: { ...values, email : ${values.email} , password: ${values.password} , username: ${values.username}` }}); console.log(values)}` and get Error TypeError: createUser is not a function at Object.handleSubmitsaud00
createUser is already defined in component [global] scope, you don't need to define it as handleSubmit argumentxadm
Now Error "Line 149:6: 'createUser' is not defined no-undef"saud00
hmmm...withFormik, as HOC is outside ... convert it to useFormik, declare right after useMutation ? ... or place <FormikApp/> inside some functional component with 'useMutation` ... move mutation outside .... const MutationWithFormik = () => { const [createUser] = useMutation(REGISTER_MUTATION); return <FormikApp createUser />;} ... use props.createUser in handleSubmit ... of course render MutationWithFormik as mainxadm

1 Answers

2
votes

In your form.js don't do this render(<FormikApp />, document.getElementById("root"))

You're rendering <FormikApp /> and as you can see, you need to wrap <FormikApp /> using ApolloProvider because useMutation requires apollo client.

if you remove render(<FormikApp />, document.getElementById("root")), I believe your problem wouldn't persist

Edit

Working example: https://codesandbox.io/s/awesome-ishizaka-kuhxi

You can make a wrapper for your FormikApp. Something like this:

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;