Friday, 18 January 2019

Access updated FormikProps after arrayHelper function runs

I have the following code:

  addLineItem = (formProps: FormikProps<MyEntity>, arrayHelpers: ArrayHelpers) => {
    arrayHelpers.push(getNewEntity(formProps.values.date));
    reassignLineItemIds(formProps);
  };

The problem I'm experiencing is that reassignLineItemIds needs the updated values in formProps and I don't have access to the updated version of formProps after arrayHelpers.push() has run.

One solution I came across involved creating the following component:


interface ConnectedProps {
  delay?: number;
  onChange: (prevProps: FormikProps<MyEntity>, nextProps: FormikProps<MyEntity>) => void;
}

interface OwnProps extends ConnectedProps {
  formik: FormikProps<FormikValues>;
}

class FormChangeHandler extends Component<OwnProps> {
  onChange = debounce(this.props.onChange, this.props.delay || 0);

  componentDidUpdate(prevProps: OwnProps) {
    const { formik } = this.props;
    const { isValid } = formik;

    const hasChanged = !isEqual(prevProps.formik.values, formik.values);
    const shouldCallback = isValid && hasChanged;

    if (shouldCallback) {
      this.onChange(prevProps.formik as FormikProps<MyEntity>, formik as FormikProps<MyEntity>);
    }
  }

  render() {
    return null;
  }
}

const connected = connect<ConnectedProps>(FormChangeHandler);

export { connected as FormChangeHandler };

Then, in my Formik <Form>, include the following:

<FormChangeHandler onChange={
    (prevProps: FormikProps<MyEntity>, nextProps: FormikProps<MyEntity>) => {
        if (getLineItemCount(prevProps.values) !== getLineItemCount(nextProps.values)) {
        reassignLineItemIds(nextProps);
    }
}} />

This works, but it will have negative performance impacts and just seems like a crazy hoop to jump through.



from Access updated FormikProps after arrayHelper function runs

No comments:

Post a Comment