Skip to content

Commit db8cd78

Browse files
committed
replaced redux-form with formik
1 parent eb6e708 commit db8cd78

12 files changed

Lines changed: 283 additions & 145 deletions

File tree

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
},
1515
"dependencies": {
1616
"axios": "0.18.0",
17+
"formik": "^1.5.8",
1718
"prop-types": "15.7.2",
1819
"react": "16.8.3",
1920
"react-native": "0.59.8",
@@ -25,9 +26,9 @@
2526
"react-redux": "7.1.1",
2627
"redux": "4.0.4",
2728
"redux-act": "1.7.7",
28-
"redux-form": "8.2.6",
2929
"redux-persist": "6.0.0",
30-
"redux-saga": "1.1.1"
30+
"redux-saga": "1.1.1",
31+
"yup": "^0.27.0"
3132
},
3233
"devDependencies": {
3334
"@babel/core": "^7.4.4",

src/components/AuthFormInput/index.js

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,57 +9,64 @@ import styles from './styles';
99

1010
const FormInput = (props) => {
1111
const {
12-
input,
1312
containerStyle,
1413
inputContainerStyle,
15-
meta: { error, touched },
1614
inlineImage,
15+
name,
16+
handleChange,
17+
handleBlur,
18+
errors,
19+
touched,
20+
value,
1721
...inputProps
1822
} = props;
1923

24+
const hasError = touched[name] && errors[name];
25+
2026
const renderError = () => {
21-
if (touched && error) {
22-
return <DefaultText>{error}</DefaultText>;
27+
if (hasError) {
28+
return <DefaultText>{errors[name]}</DefaultText>;
2329
}
2430
return null;
2531
};
2632

33+
2734
return (
2835
<View style={[styles.container, containerStyle]}>
2936
<View
3037
style={[
3138
styles.inputContainer,
3239
inputContainerStyle,
33-
(error && touched) ? styles.errorInput : null,
40+
(hasError) ? styles.errorInput : null,
3441
]}
3542
>
3643
<DefaultInput
3744
style={styles.input}
3845
{...inputProps}
39-
onChangeText={input.onChange}
40-
onBlur={input.onBlur}
41-
onFocus={input.onFocus}
42-
value={input.value}
46+
onChangeText={handleChange(name)}
47+
onBlur={handleBlur(name)}
48+
value={inputProps.value}
4349
/>
4450
</View>
4551
<View style={styles.errorContainer}>
46-
{
47-
renderError()
48-
}
52+
{renderError()}
4953
</View>
5054
</View>
5155
);
5256
};
5357

5458
FormInput.propTypes = {
59+
...DefaultInput.propTypes,
5560
input: PropTypes.object,
5661
containerStyle: PropTypes.any,
57-
meta: PropTypes.shape({
58-
touched: PropTypes.bool,
59-
error: PropTypes.any,
60-
}),
6162
inlineImage: PropTypes.any,
6263
inputContainerStyle: PropTypes.any,
64+
name: PropTypes.string.isRequired,
65+
handleChange: PropTypes.func,
66+
handleBlur: PropTypes.func,
67+
errors: PropTypes.object,
68+
touched: PropTypes.object,
69+
value: DefaultInput.propTypes.value,
6370
};
6471

6572
export default FormInput;

src/components/DefaultInput/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ const DefaultInput = ({ inputRef, style, ...rest }) => (
1818
);
1919

2020
DefaultInput.propTypes = {
21+
...TextInput.propTypes,
2122
inputRef: PropTypes.any,
2223
style: PropTypes.any,
2324
};

src/redux/reducers/index.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
import { combineReducers } from 'redux';
2-
import { reducer as form } from 'redux-form';
32
import nav from '../../navigation/reducer';
43
import auth from './auth';
54

65
const reducer = combineReducers({
7-
form,
86
nav,
97
auth,
108
});
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
import { Formik } from 'formik';
4+
import { object, string } from 'yup';
5+
6+
const SignInSchema = object().shape({
7+
email: string()
8+
.email('Invalid email')
9+
.required('Required'),
10+
password: string().required('Required'),
11+
});
12+
13+
const INITIAL_SIGN_IN_VALUES = {
14+
email: '',
15+
password: '',
16+
};
17+
18+
const FormProvider = ({ children, onSubmit }) => {
19+
/* :: (object, object) -> Promise<void> */
20+
const handleSignIn = async (formData, actions) => {
21+
try {
22+
onSubmit(formData);
23+
} catch (error) {
24+
actions.resetForm();
25+
actions.setFieldValue('email', formData.email);
26+
}
27+
};
28+
29+
return (
30+
<Formik
31+
initialValues={{ ...INITIAL_SIGN_IN_VALUES }}
32+
validationSchema={SignInSchema}
33+
onSubmit={handleSignIn}
34+
>
35+
{children}
36+
</Formik>
37+
);
38+
};
39+
40+
FormProvider.propTypes = {
41+
onSubmit: PropTypes.func.isRequired,
42+
children: PropTypes.oneOfType([PropTypes.element, PropTypes.func]).isRequired,
43+
};
44+
45+
export default FormProvider;

src/screens/SignInScreen/SignIn.js

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,13 @@
11
import React, { useRef } from 'react';
2-
import { View, Keyboard } from 'react-native';
3-
import { reduxForm, Field } from 'redux-form';
2+
import { View } from 'react-native';
43
import PropTypes from 'prop-types';
5-
64
import KeyboardAvoidingWrapper from '../../components/KeyboardAvoidingWrapper';
75
import FormInput from '../../components/AuthFormInput';
86
import DefaultButton from '../../components/DefaultButton';
97
import DefaultText from '../../components/DefaultText';
10-
11-
import validate from '../../validators/auth-validator';
128
import styles from './styles';
139

14-
const SignIn = ({ handleSubmit }) => {
15-
const submit = (data) => {
16-
Keyboard.dismiss();
17-
handleSubmit(data);
18-
};
19-
10+
const SignIn = ({ handleSubmit, values, ...props }) => {
2011
const renderTitle = () => (
2112
<DefaultText
2213
large
@@ -33,31 +24,33 @@ const SignIn = ({ handleSubmit }) => {
3324
<View style={{ flex: 1 }}>
3425
<KeyboardAvoidingWrapper>
3526
{ renderTitle() }
36-
<Field
37-
component={FormInput}
38-
placeholder={'EMAIL'}
27+
<FormInput
28+
placeholder='EMAIL'
3929
name='email'
4030
autoCapitalize='none'
4131
returnKeyType='next'
4232
onSubmitEditing={() => passwordRef.current.focus()}
4333
keyboardType='email-address'
4434
maxLength={40}
35+
value={values.email}
36+
{...props}
4537
/>
46-
<Field
47-
component={FormInput}
48-
placeholder={'PASSWORD'}
38+
<FormInput
39+
placeholder='PASSWORD'
4940
containerStyle={styles.lastInput}
5041
name='password'
5142
autoCapitalize='none'
5243
returnKeyType='done'
5344
inputRef={passwordRef}
5445
secureTextEntry
55-
onSubmitEditing={submit}
46+
onSubmitEditing={handleSubmit}
5647
maxLength={20}
48+
value={values.password}
49+
{...props}
5750
/>
5851
<DefaultButton
5952
title={'Sign in'}
60-
onPress={submit}
53+
onPress={handleSubmit}
6154
/>
6255
</KeyboardAvoidingWrapper>
6356
</View>
@@ -66,6 +59,7 @@ const SignIn = ({ handleSubmit }) => {
6659

6760
SignIn.propTypes = {
6861
handleSubmit: PropTypes.func,
62+
values: PropTypes.object,
6963
};
7064

71-
export default reduxForm({ form: 'signin', validate })(SignIn);
65+
export default SignIn;

src/screens/SignInScreen/index.js

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,29 @@
11
import React from 'react';
22
import PropTypes from 'prop-types';
33
import { connect } from 'react-redux';
4+
import { Keyboard } from 'react-native';
45

6+
import FormProvider from './FormProvider';
57
import SignIn from './SignIn';
68
import { signInAction } from '../../redux/actions';
79

8-
const LoginScreen = ({ signIn, navigation }) => (
9-
<SignIn
10-
onSubmit={signIn}
11-
onGoToSignUpPress={() => navigation.replace('SignUpScreen')}
12-
/>
13-
);
10+
const LoginScreen = ({ signIn, navigation }) => {
11+
const handleSubmit = (data) => {
12+
Keyboard.dismiss();
13+
signIn(data);
14+
};
15+
16+
return (
17+
<FormProvider onSubmit={handleSubmit}>
18+
{props => (
19+
<SignIn
20+
onGoToSignUpPress={() => navigation.replace('SignUpScreen')}
21+
{...props}
22+
/>
23+
)}
24+
</FormProvider>
25+
);
26+
};
1427

1528
LoginScreen.propTypes = {
1629
navigation: PropTypes.object,
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
import { Formik } from 'formik';
4+
import { object, string } from 'yup';
5+
6+
const SignUpSchema = object().shape({
7+
firstName: string().required('Required'),
8+
lastName: string().required('Required'),
9+
email: string()
10+
.email('Invalid email')
11+
.required('Required'),
12+
password: string().required('Required'),
13+
});
14+
15+
const INITIAL_SIGN_UP_VALUES = {
16+
firstName: '',
17+
lastName: '',
18+
email: '',
19+
password: '',
20+
};
21+
22+
const FormProvider = ({ children, onSubmit }) => {
23+
/* :: (object, object) -> Promise<void> */
24+
const handleSignIn = async (formData, actions) => {
25+
try {
26+
onSubmit(formData);
27+
} catch (error) {
28+
actions.resetForm();
29+
}
30+
};
31+
32+
return (
33+
<Formik
34+
initialValues={{ ...INITIAL_SIGN_UP_VALUES }}
35+
validationSchema={SignUpSchema}
36+
onSubmit={handleSignIn}
37+
>
38+
{children}
39+
</Formik>
40+
);
41+
};
42+
43+
FormProvider.propTypes = {
44+
onSubmit: PropTypes.func.isRequired,
45+
children: PropTypes.oneOfType([PropTypes.element, PropTypes.func]).isRequired,
46+
};
47+
48+
export default FormProvider;

0 commit comments

Comments
 (0)