Skip to content

Instantly share code, notes, and snippets.

@sbrichardson
Forked from mwickett/formikApollo.js
Created November 19, 2017 02:55
Show Gist options
  • Save sbrichardson/e95829c04bdf79ea8c306bd555b04558 to your computer and use it in GitHub Desktop.
Save sbrichardson/e95829c04bdf79ea8c306bd555b04558 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='you@yourdomain.com'
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))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment