|
import React, { useMemo, useCallback } from 'react'; |
|
import PropTypes from 'prop-types'; |
|
|
|
import _ from 'lodash'; |
|
|
|
import { FastField as BaseFastField } from 'formik'; |
|
|
|
const nameShouldUpdate = (nextFormik, formik, name) => { |
|
return ( |
|
_.get(formik.values, name) !== _.get(nextFormik.values, name) || |
|
_.get(formik.errors, name) !== _.get(nextFormik.errors, name) || |
|
_.get(formik.touched, name) !== _.get(nextFormik.touched, name) |
|
); |
|
}; |
|
|
|
const defaultShouldUpdate = (nextProps, props) => { |
|
const { name } = props; |
|
return ( |
|
nameShouldUpdate(nextProps.formik, props.formik, name) || |
|
Object.keys(props).length !== Object.keys(nextProps).length || |
|
props.formik.isSubmitting !== nextProps.formik.isSubmitting |
|
); |
|
}; |
|
|
|
const FastField = ({ names, deps: propDeps, ...restProps }) => { |
|
// shallow check for updates |
|
const deps = useMemo(() => propDeps, propDeps); |
|
|
|
// shouldn't change after mount |
|
const shouldUpdate = useCallback((nextProps, props) => { |
|
if (props.deps !== nextProps.deps) { |
|
return true; |
|
} |
|
|
|
if (defaultShouldUpdate(nextProps, props)) { |
|
return true; |
|
} |
|
|
|
let update = false; |
|
_.each(names, name => { |
|
if (update) { |
|
return; |
|
} |
|
if (nameShouldUpdate(nextProps.formik, props.formik, name)) { |
|
update = true; |
|
} |
|
}); |
|
|
|
return update; |
|
}, []); |
|
|
|
return ( |
|
<BaseFastField shouldUpdate={shouldUpdate} {...restProps} deps={deps} /> |
|
); |
|
}; |
|
FastField.propTypes = { |
|
names: PropTypes.array, // specified formik names |
|
deps: PropTypes.array, // specified value deps |
|
}; |
|
FastField.defaultProps = { |
|
names: [], |
|
deps: [], |
|
}; |
|
|
|
export default FastField; |