Skip to content

Instantly share code, notes, and snippets.

@mwickett
Last active December 20, 2022 23:00
Show Gist options
  • Save mwickett/2aecfdeea40daa07d39e11922ae1fe20 to your computer and use it in GitHub Desktop.
Save mwickett/2aecfdeea40daa07d39e11922ae1fe20 to your computer and use it in GitHub Desktop.
Formik + Apollo
import React from 'react'
import { withRouter, Link } from 'react-router-dom'
import { graphql, compose } from 'react-apollo'
import { Formik } from 'formik'
import Yup from 'yup'
import FormWideError from '../elements/form/FormWideError'
import TextInput from '../elements/form/TextInput'
import Button from '../elements/form/Button'
import { H2 } from '../elements/text/Headings'
import Wrapper from '../elements/layout/Wrapper'
import CurrentUser from '../queries/CurrentUser'
import signinUser from '../mutations/signinUser'
const handleSubmit = (payload, { props, setSubmitting, setErrors }) => {
const {email, password} = payload
props.signinUser({ variables: { email, password } })
.then((response) => {
window.localStorage.setItem('graphcoolToken', response.data.signinUser.token)
props.data.refetch()
props.history.push('/')
}).catch((e) => {
const errors = e.graphQLErrors.map(error => error.message)
console.log(errors)
setSubmitting(false)
setErrors({ email: ' ', password: ' ', form: errors })
})
}
const LoginForm = ({
handleSubmit,
errors,
touched,
values,
handleChange,
handleBlur,
isSubmitting
}) =>
<Wrapper>
<H2>Sign In</H2>
<FormWideError error={errors.form} />
<form onSubmit={handleSubmit}>
<TextInput
id='email'
type='email'
label='Email'
placeholder='[email protected]'
error={errors.email && touched.email && errors.email}
value={values.email}
onChange={handleChange}
onBlur={handleBlur}
/>
<TextInput
id='password'
type='password'
label='Password'
placeholder=''
error={errors.password && touched.password && errors.password}
value={values.password}
onChange={handleChange}
onBlur={handleBlur}
/>
<Button
primary
type='submit'
disabled={
isSubmitting ||
!!(errors.email && touched.email) ||
!!(errors.password && touched.password)
}
>
Sign In
</Button>
</form>
</Wrapper>
const LoginFormWithGraphQL = compose(
graphql(signinUser, {name: 'signinUser'}),
graphql(CurrentUser, { options: { fetchPolicy: 'network-only' } }),
Formik({
validationSchema: Yup.object().shape({
email: Yup.string()
.email('Invalid email address')
.required('Email is required'),
password: Yup.string()
.required('Password is required')
}),
mapPropsToValues: ({ variables }) => ({
...variables
}),
handleSubmit: handleSubmit,
displayName: 'Login'
})
)(LoginForm)
const LoginFormWithRouter = withRouter(LoginFormWithGraphQL)
class Login extends React.Component {
componentWillUpdate (nextProps) {
if (!this.props.data.user && nextProps.data.user) {
this.props.history.push('/dashboard')
}
}
render () {
if (this.props.data.loading) {
return (<div></div>)
}
return (
<div>
<LoginFormWithRouter variables={{ email: '', password: '' }} />
<p>Don't have an account? <Link to='/signup'>Create one now</Link></p>
</div>
)
}
}
// Set network fetch policy to network only for security reasons
export default graphql(CurrentUser, { options: { fetchPolicy: 'network-only' } })(withRouter(Login))
@rigalpatel001
Copy link

Use the below code example. It works fine.

import React,{ useState } from "react";
import { StyleSheet, Image ,Text } from "react-native";
import * as Yup from "yup";
import { gql, useQuery,useMutation } from '@apollo/client';

import Screen from "../components/Screen";
import { ErrorMessage,Form, FormField, SubmitButton } from "../components/forms";
import ActivityIndicator from "../components/ActivityIndicator";
import useAuth from "../auth/useAuth";


const validationSchema = Yup.object().shape({
  email: Yup.string().required().email().label("Email"),
  password: Yup.string().required().min(4).label("Password"),
});

const LOG_IN = gql`
mutation SignInMutation($signInLogin: String!, $signInPassword: String!) {
  signIn(login: $signInLogin, password: $signInPassword) {
    token
  }
}
`;
function LoginScreen(props) {

  const auth = useAuth();
  const [loginFailed, setLoginFailed] = useState(false);
  const [isloading, setIsloading] = useState(false);

  const handleSubmit = async ({ email, password }) => {
    setIsloading(true);
   try {
    const result = await signIn({ variables: { signInLogin: email,signInPassword:password } });
    setIsloading(false);
    auth.logIn(result.data.signIn.token);
   } catch (error) {
    console.log("Error", error);
    setLoginFailed(true);
    setIsloading(false);
   }
  };

   const [signIn, { data, loading, error }] = useMutation(LOG_IN);
   //if (loading) return <Text>Submitting...</Text>
   //if (error) setLoginFailed(true);

  return (
    <>
    <ActivityIndicator visible={isloading} />
    <Screen style={styles.container}>
      <Image style={styles.logo} source={require("../assets/logo.png")} />
      <Form
        initialValues={{ email: "", password: "" }}
        onSubmit={handleSubmit}
        validationSchema={validationSchema}
      >
         <ErrorMessage
          error="Invalid email and/or password."
          visible={loginFailed}
        />
        <FormField
          autoCapitalize="none"
          autoCorrect={false}
          icon="email"
          keyboardType="email-address"
          name="email"
          placeholder="Email"
          textContentType="emailAddress"
        />
        <FormField
          autoCapitalize="none"
          autoCorrect={false}
          icon="lock"
          name="password"
          placeholder="Password"
          secureTextEntry
          textContentType="password"
        />
        <SubmitButton title="Login" />
      </Form>
    </Screen>
    </>
  );
}

const styles = StyleSheet.create({
  container: {
    padding: 10,
  },
  logo: {
    width: 200,
    height: 80,
    alignSelf: "center",
    marginTop: 50,
    marginBottom: 20,
  },
});

export default LoginScreen;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment