Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React 16.3 #594

Merged
merged 28 commits into from May 11, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
04bec6f
Attempt move to React 16.3
jaredpalmer Apr 22, 2018
e439bb7
Add back React as peer dep
jaredpalmer Apr 22, 2018
6deb4a7
Add hoist-non-react-statics to connect()
jaredpalmer Apr 22, 2018
c16c8e8
Remove any from hoistStatics in withFormik()
jaredpalmer Apr 22, 2018
c981f97
Introduct FormikContext<V> interface in addition to FormikProps<V>
jaredpalmer Apr 22, 2018
d83172d
Merge branch 'master' into react-16.3
jaredpalmer May 2, 2018
0a82cac
Use a forked version of Enzyme that's compatible with React 16 :shrug:
jaredpalmer May 9, 2018
3a7667e
Expose WrappedComponent with connect
jaredpalmer May 9, 2018
78b01a6
Move from cWM to cDM in Formik tests
jaredpalmer May 9, 2018
b581d74
Start to use WrappedComponent in <Field> tests
jaredpalmer May 9, 2018
1ba647a
Use WrappedComponent in FastField tests
jaredpalmer May 9, 2018
a90eb92
Fix FastField innerRef test
jaredpalmer May 9, 2018
f3f591a
Fix usage of getDerivedStateFromProps
jaredpalmer May 9, 2018
cbf1643
Remove @types/enzyme
jaredpalmer May 9, 2018
4f29a85
Add back react as a peer dependency
jaredpalmer May 9, 2018
8ac6c4f
Bump React version on website
jaredpalmer May 9, 2018
99ccab8
Install formik from filesystem on website
jaredpalmer May 9, 2018
7fd5f1e
Fix types for Field and FastField
jaredpalmer May 11, 2018
3a3b10b
v1.0.0-alpha.r16.3.1
jaredpalmer May 11, 2018
ff344ff
Bump typescript version to 2.8.3
jaredpalmer May 11, 2018
9e9e0cd
v1.0.0-alpha.r16.3.2
jaredpalmer May 11, 2018
fe812c2
Remove Fragment and export connect()
jaredpalmer May 11, 2018
164f0e6
Fix 16.3 builds
jaredpalmer May 11, 2018
1968a7f
Use esModuleInterop
jaredpalmer May 11, 2018
7c01ab0
Fix builds, expose dev build like React does
jaredpalmer May 11, 2018
fe82f04
Move types to another directory
jaredpalmer May 11, 2018
55d00f0
Fix size-limit
jaredpalmer May 11, 2018
fabf5b0
Add back size-limit
jaredpalmer May 11, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 5 additions & 7 deletions package.json
Expand Up @@ -37,24 +37,21 @@
"size": "size-limit"
},
"dependencies": {
"create-react-context": "^0.2.2",
"hoist-non-react-statics": "^2.5.0",
"lodash.clonedeep": "^4.5.0",
"lodash.topath": "4.5.2",
"prop-types": "^15.5.10",
"react-fast-compare": "^1.0.0",
"warning": "^3.0.0"
},
"peerDependencies": {
"react": ">=15"
},
"peerDependencies": {},
"optionalDependencies": {},
"devDependencies": {
"@types/enzyme": "3.1.5",
"@types/enzyme-adapter-react-16": "1.0.1",
"@types/jest": "20.0.6",
"@types/lodash.clonedeep": "^4.5.3",
"@types/lodash.topath": "4.5.3",
"@types/prop-types": "^15.5.2",
"@types/react": "16.0.28",
"@types/react-dom": "^16.0.3",
"@types/react-test-renderer": "15.5.2",
Expand All @@ -69,8 +66,9 @@
"jest-cli": "^21.2.1",
"lint-staged": "4.0.2",
"prettier": "1.11.1",
"react": "16.2.0",
"react-dom": "16.2.0",
"prop-types": "^15.6.1",
"react": "^16.3.2",
"react-dom": "^16.3.2",
"rimraf": "^2.6.2",
"rollup": "^0.55.3",
"rollup-plugin-commonjs": "8.1.0",
Expand Down
65 changes: 28 additions & 37 deletions src/FastField.tsx
@@ -1,10 +1,11 @@
import * as PropTypes from 'prop-types';
import * as React from 'react';
import { validateYupSchema, yupToFormErrors, FormikProps } from './Formik';
import { getIn, isPromise, setIn, isFunction, isEmptyChildren } from './utils';
import isEqual from 'react-fast-compare';
import warning from 'warning';
import { FieldAttributes, FieldConfig, FieldProps } from './Field';
import isEqual from 'react-fast-compare';
import { validateYupSchema, yupToFormErrors } from './Formik';
import { connect } from './connect';
import { FormikProps } from './types';
import { getIn, isEmptyChildren, isFunction, isPromise, setIn } from './utils';

export interface FastFieldState {
value: any;
Expand All @@ -20,46 +21,34 @@ function isEqualExceptForKey(a: any, b: any, path: string) {
* Custom Field component for quickly hooking into Formik
* context and wiring up forms.
*/
export class FastField<
Props extends FieldAttributes = any
> extends React.Component<Props, FastFieldState> {
static contextTypes = {
formik: PropTypes.object,
};

static propTypes = {
name: PropTypes.string.isRequired,
component: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
render: PropTypes.func,
children: PropTypes.oneOfType([PropTypes.func, PropTypes.node]),
validate: PropTypes.func,
innerRef: PropTypes.func,
};

reset: Function;
constructor(props: Props, context: any) {
class FastFieldInner<
Props extends FieldAttributes = any,
Values = {}
> extends React.Component<
Props & { formik: FormikProps<Values> },
FastFieldState
> {
reset: (nextValues?: any) => void;
constructor(props: Props & { formik: FormikProps<Values> }) {
super(props);
this.state = {
value: getIn(context.formik.values, props.name),
error: getIn(context.formik.errors, props.name),
value: getIn(props.formik.values, props.name),
error: getIn(props.formik.errors, props.name),
};

this.reset = (nextValues?: any) => {
this.setState({
value: getIn(nextValues, props.name),
error: getIn(context.formik.errors, props.name),
error: getIn(props.formik.errors, props.name),
});
};

context.formik.registerField(props.name, this.reset);
props.formik.registerField(props.name, this.reset);
}

componentWillReceiveProps(
nextProps: Props,
nextContext: { formik: FormikProps<any> }
) {
const nextFieldValue = getIn(nextContext.formik.values, nextProps.name);
const nextFieldError = getIn(nextContext.formik.errors, nextProps.name);
componentWillReceiveProps(nextProps: Props & { formik: FormikProps<any> }) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Migration to getDeriveStateFromProps can be achieved with react-lifecycles-compat

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call

const nextFieldValue = getIn(nextProps.formik.values, nextProps.name);
const nextFieldError = getIn(nextProps.formik.errors, nextProps.name);

let nextState: any;

Expand All @@ -77,7 +66,7 @@ export class FastField<
}

componentWillUnmount() {
this.context.formik.unregisterField(this.props.name);
this.props.formik.unregisterField(this.props.name);
}

componentWillMount() {
Expand Down Expand Up @@ -108,7 +97,7 @@ export class FastField<
validationSchema,
errors,
setFormikState,
} = this.context.formik;
} = this.props.formik;
const { type, value, checked } = e.target;
const val = /number|range/.test(type)
? parseFloat(value)
Expand Down Expand Up @@ -213,7 +202,7 @@ export class FastField<
};

handleBlur = () => {
const { validateOnBlur, setFormikState } = this.context.formik;
const { validateOnBlur, setFormikState } = this.props.formik;
const { name, validate } = this.props;

// @todo refactor
Expand Down Expand Up @@ -261,10 +250,10 @@ export class FastField<
render,
children,
component = 'input',
formik,
...props
} = this.props as FieldConfig;
} = this.props as FieldConfig & { formik: FormikProps<Values> };

const { formik } = this.context;
const field = {
value:
props.type === 'radio' || props.type === 'checkbox'
Expand Down Expand Up @@ -309,3 +298,5 @@ export class FastField<
});
}
}

export const FastField = connect<FieldAttributes, any>(FastFieldInner);
44 changes: 15 additions & 29 deletions src/Field.tsx
@@ -1,10 +1,8 @@
import * as PropTypes from 'prop-types';
import * as React from 'react';

import { FormikProps } from './Formik';
import { getIn, isPromise, isFunction, isEmptyChildren } from './utils';
import warning from 'warning';
import { GenericFieldHTMLAttributes } from './types';
import { connect } from './connect';
import { FormikProps, GenericFieldHTMLAttributes } from './types';
import { getIn, isEmptyChildren, isFunction, isPromise } from './utils';

/**
* Note: These typings could be more restrictive, but then it would limit the
Expand Down Expand Up @@ -84,24 +82,10 @@ export type FieldAttributes = GenericFieldHTMLAttributes & FieldConfig;
* Custom Field component for quickly hooking into Formik
* context and wiring up forms.
*/

export class Field<Props extends FieldAttributes = any> extends React.Component<
Props,
{}
> {
static contextTypes = {
formik: PropTypes.object,
};

static propTypes = {
name: PropTypes.string.isRequired,
component: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
render: PropTypes.func,
children: PropTypes.oneOfType([PropTypes.func, PropTypes.node]),
validate: PropTypes.func,
innerRef: PropTypes.func,
};

class FieldInner<
Props extends FieldAttributes = any,
Values = {}
> extends React.Component<Props & { formik: FormikProps<Values> }, {}> {
componentWillMount() {
const { render, children, component } = this.props;

Expand All @@ -122,30 +106,30 @@ export class Field<Props extends FieldAttributes = any> extends React.Component<
}

handleChange = (e: React.ChangeEvent<any>) => {
const { handleChange, validateOnChange } = this.context.formik;
const { handleChange, validateOnChange } = this.props.formik;
handleChange(e); // Call Formik's handleChange no matter what
if (!!validateOnChange && !!this.props.validate) {
this.runFieldValidations(e.target.value);
}
};

handleBlur = (e: any) => {
const { handleBlur, validateOnBlur } = this.context.formik;
const { handleBlur, validateOnBlur } = this.props.formik;
handleBlur(e); // Call Formik's handleBlur no matter what
if (validateOnBlur && this.props.validate) {
this.runFieldValidations(e.target.value);
}
};

runFieldValidations = (value: any) => {
const { setFieldError } = this.context.formik;
const { setFieldError } = this.props.formik;
const { name, validate } = this.props;
// Call validate fn
const maybePromise = (validate as any)(value);
// Check if validate it returns a Promise
if (isPromise(maybePromise)) {
(maybePromise as Promise<any>).then(
() => setFieldError(name, undefined),
() => setFieldError(name, undefined as any),
error => setFieldError(name, error)
);
} else {
Expand All @@ -161,10 +145,10 @@ export class Field<Props extends FieldAttributes = any> extends React.Component<
render,
children,
component = 'input',
formik,
...props
} = this.props as FieldConfig;
} = this.props as FieldConfig & { formik: FormikProps<Values> };

const { formik } = this.context;
const field = {
value:
props.type === 'radio' || props.type === 'checkbox'
Expand Down Expand Up @@ -201,3 +185,5 @@ export class Field<Props extends FieldAttributes = any> extends React.Component<
});
}
}

export const Field = connect<FieldAttributes, any>(FieldInner);
31 changes: 14 additions & 17 deletions src/FieldArray.tsx
@@ -1,8 +1,7 @@
import * as PropTypes from 'prop-types';
import * as React from 'react';
import { FormikProps, FormikState } from './Formik';
import { isEmptyChildren, getIn, setIn, isFunction } from './utils';
import { SharedRenderProps } from './types';
import { connect } from './connect';
import { FormikProps, FormikState, SharedRenderProps } from './types';
import { getIn, isEmptyChildren, isFunction, setIn } from './utils';

export type FieldArrayConfig = {
/** Really the path to the array field to be updated */
Expand Down Expand Up @@ -76,16 +75,15 @@ export const replace = (array: any[], index: number, value: any) => {
copy[index] = value;
return copy;
};

export class FieldArray extends React.Component<FieldArrayConfig, {}> {
class FieldArrayInner<Values = {}> extends React.Component<
FieldArrayConfig & { formik: FormikProps<Values> },
{}
> {
static defaultProps = {
validateOnChange: true,
};
static contextTypes = {
formik: PropTypes.object,
};

constructor(props: FieldArrayConfig) {
constructor(props: FieldArrayConfig & { formik: FormikProps<Values> }) {
super(props);
// We need TypeScript generics on these, so we'll bind them in the constructor
this.remove = this.remove.bind(this);
Expand All @@ -98,13 +96,10 @@ export class FieldArray extends React.Component<FieldArrayConfig, {}> {
alterErrors: boolean
) => {
const {
setFormikState,
validateForm,
values,
touched,
errors,
} = this.context.formik;
const { name, validateOnChange } = this.props;
name,
validateOnChange,
formik: { setFormikState, validateForm, values, touched, errors },
} = this.props;
setFormikState(
(prevState: FormikState<any>) => ({
...prevState,
Expand Down Expand Up @@ -265,3 +260,5 @@ export class FieldArray extends React.Component<FieldArrayConfig, {}> {
: null;
}
}

export const FieldArray = connect<FieldArrayConfig, any>(FieldArrayInner);
12 changes: 4 additions & 8 deletions src/Form.tsx
@@ -1,10 +1,6 @@
import * as PropTypes from 'prop-types';
import * as React from 'react';
import { connect } from './connect';

export const Form: React.SFC<any> = (props, context) => (
<form onSubmit={context.formik.handleSubmit} {...props} />
);

Form.contextTypes = {
formik: PropTypes.object,
};
export const Form = connect<any>(({ formik: { handleSubmit }, ...props }) => (
<form onSubmit={handleSubmit} {...props} />
));