redux-form
Version:
A higher order component decorator for forms using Redux and React
200 lines (176 loc) • 7.43 kB
JavaScript
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/objectWithoutPropertiesLoose";
import _createClass from "@babel/runtime/helpers/createClass";
import _inheritsLoose from "@babel/runtime/helpers/inheritsLoose";
import _mapValues from "lodash/mapValues";
import React, { Component, createElement } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import createFieldArrayProps from './createFieldArrayProps';
import plain from './structure/plain';
import validateComponentProp from './util/validateComponentProp';
var propsToNotUpdateFor = ['_reduxForm', 'value'];
export default function createConnectedFieldArray(structure) {
var deepEqual = structure.deepEqual,
getIn = structure.getIn,
size = structure.size,
equals = structure.equals,
orderChanged = structure.orderChanged;
var getSyncError = function getSyncError(syncErrors, name) {
// For an array, the error can _ONLY_ be under _error.
// This is why this getSyncError is not the same as the
// one in Field.
return plain.getIn(syncErrors, name + "._error");
};
var getSyncWarning = function getSyncWarning(syncWarnings, name) {
// For an array, the warning can _ONLY_ be under _warning.
// This is why this getSyncError is not the same as the
// one in Field.
return getIn(syncWarnings, name + "._warning");
};
var ConnectedFieldArray =
/*#__PURE__*/
function (_Component) {
_inheritsLoose(ConnectedFieldArray, _Component);
function ConnectedFieldArray() {
var _this;
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
_this = _Component.call.apply(_Component, [this].concat(args)) || this;
_this.ref = React.createRef();
_this.getValue = function (index) {
return _this.props.value && getIn(_this.props.value, String(index));
};
return _this;
}
var _proto = ConnectedFieldArray.prototype;
_proto.shouldComponentUpdate = function shouldComponentUpdate(nextProps) {
var _this2 = this;
// Update if the elements of the value array was updated.
var thisValue = this.props.value;
var nextValue = nextProps.value;
if (thisValue && nextValue) {
var nextValueItemsSame = equals(nextValue, thisValue); //.every(val => ~thisValue.indexOf(val))
var nextValueItemsOrderChanged = orderChanged(thisValue, nextValue);
var thisValueLength = thisValue.length || thisValue.size;
var nextValueLength = nextValue.length || nextValue.size;
if (thisValueLength !== nextValueLength || nextValueItemsSame && nextValueItemsOrderChanged || nextProps.rerenderOnEveryChange && thisValue.some(function (val, index) {
return !deepEqual(val, nextValue[index]);
})) {
return true;
}
}
var nextPropsKeys = Object.keys(nextProps);
var thisPropsKeys = Object.keys(this.props); // if we have children, we MUST update in React 16
// https://twitter.com/erikras/status/915866544558788608
return !!(this.props.children || nextProps.children || nextPropsKeys.length !== thisPropsKeys.length || nextPropsKeys.some(function (prop) {
// useful to debug rerenders
// if (!plain.deepEqual(this.props[ prop ], nextProps[ prop ])) {
// console.info(prop, 'changed', this.props[ prop ], '==>', nextProps[ prop ])
// }
return !~propsToNotUpdateFor.indexOf(prop) && !deepEqual(_this2.props[prop], nextProps[prop]);
}));
};
_proto.getRenderedComponent = function getRenderedComponent() {
return this.ref.current;
};
_proto.render = function render() {
var _this$props = this.props,
component = _this$props.component,
forwardRef = _this$props.forwardRef,
name = _this$props.name,
_reduxForm = _this$props._reduxForm,
validate = _this$props.validate,
warn = _this$props.warn,
rerenderOnEveryChange = _this$props.rerenderOnEveryChange,
rest = _objectWithoutPropertiesLoose(_this$props, ["component", "forwardRef", "name", "_reduxForm", "validate", "warn", "rerenderOnEveryChange"]);
var props = createFieldArrayProps(structure, name, _reduxForm.form, _reduxForm.sectionPrefix, this.getValue, rest);
if (forwardRef) {
props.ref = this.ref;
}
return createElement(component, props);
};
_createClass(ConnectedFieldArray, [{
key: "dirty",
get: function get() {
return this.props.dirty;
}
}, {
key: "pristine",
get: function get() {
return this.props.pristine;
}
}, {
key: "value",
get: function get() {
return this.props.value;
}
}]);
return ConnectedFieldArray;
}(Component);
ConnectedFieldArray.propTypes = {
component: validateComponentProp,
props: PropTypes.object,
rerenderOnEveryChange: PropTypes.bool
};
ConnectedFieldArray.defaultProps = {
rerenderOnEveryChange: false
};
var connector = connect(function (state, ownProps) {
var name = ownProps.name,
_ownProps$_reduxForm = ownProps._reduxForm,
initialValues = _ownProps$_reduxForm.initialValues,
getFormState = _ownProps$_reduxForm.getFormState;
var formState = getFormState(state);
var initial = getIn(formState, "initial." + name) || initialValues && getIn(initialValues, name);
var value = getIn(formState, "values." + name);
var submitting = getIn(formState, 'submitting');
var syncError = getSyncError(getIn(formState, 'syncErrors'), name);
var syncWarning = getSyncWarning(getIn(formState, 'syncWarnings'), name);
var pristine = deepEqual(value, initial);
return {
asyncError: getIn(formState, "asyncErrors." + name + "._error"),
dirty: !pristine,
pristine: pristine,
state: getIn(formState, "fields." + name),
submitError: getIn(formState, "submitErrors." + name + "._error"),
submitFailed: getIn(formState, 'submitFailed'),
submitting: submitting,
syncError: syncError,
syncWarning: syncWarning,
value: value,
length: size(value)
};
}, function (dispatch, ownProps) {
var name = ownProps.name,
_reduxForm = ownProps._reduxForm;
var arrayInsert = _reduxForm.arrayInsert,
arrayMove = _reduxForm.arrayMove,
arrayPop = _reduxForm.arrayPop,
arrayPush = _reduxForm.arrayPush,
arrayRemove = _reduxForm.arrayRemove,
arrayRemoveAll = _reduxForm.arrayRemoveAll,
arrayShift = _reduxForm.arrayShift,
arraySplice = _reduxForm.arraySplice,
arraySwap = _reduxForm.arraySwap,
arrayUnshift = _reduxForm.arrayUnshift;
return _mapValues({
arrayInsert: arrayInsert,
arrayMove: arrayMove,
arrayPop: arrayPop,
arrayPush: arrayPush,
arrayRemove: arrayRemove,
arrayRemoveAll: arrayRemoveAll,
arrayShift: arrayShift,
arraySplice: arraySplice,
arraySwap: arraySwap,
arrayUnshift: arrayUnshift
}, function (actionCreator) {
return bindActionCreators(actionCreator.bind(null, name), dispatch);
});
}, undefined, {
forwardRef: true
});
return connector(ConnectedFieldArray);
}