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

Best way to implement a custom onChange that behaves like a <input /> #1243

Closed
sebastiandeutsch opened this issue Jan 15, 2019 · 5 comments

Comments

Projects
None yet
4 participants
@sebastiandeutsch
Copy link

commented Jan 15, 2019

Question

I'm building a custom Input component - I'd like to create a onChange handler which should behave similar to <input onChange={...} />. I've seen that it's recommended to use setFieldValue but then the component names are leaking into the setFieldValue callbacks. What would be the best way to satisfy the onChange interface? I've managed to successful mimic the interface like this:

const event = {
  persist: () => {},
  target: {
    type: "change",
    id: this.props.id,
    name: this.props.name,
    value: value
  }
};

this.props.onChange(event);

Another idea would be to create a SyntheticEvent (but I don't now how to create one - Facebooks documentation is a bit sparse on that issue). What's the best way to archive the desired behaviour when you want to avoid using setFieldValue. You can also say: Don't do this there will be dragons :-)

@jaredpalmer

This comment has been minimized.

Copy link
Owner

commented Feb 6, 2019

My suggestion is to make 2 components. One that is your vanilla base input with styles etc, and one that hooks into Formik via or connect(). This way you can get rid of Formik without rewriting every form in your app.

@sebastiandeutsch

This comment has been minimized.

Copy link
Author

commented Feb 6, 2019

Thanks for the answer. But it mimicking the event as described ok? Then I could live with just one component.

@jaredpalmer

This comment has been minimized.

Copy link
Owner

commented Feb 6, 2019

I think you should use setFieldValue. That's what it is meant for.

@techieshark

This comment has been minimized.

Copy link

commented Mar 20, 2019

Thanks for the question & advice above ^.

In case anyone needs an example of using this, here's my code which connects a custom component's event handler (onDayChange) to setFieldValue:

// @flow
import React from 'react';
import { connect } from 'formik';

import { InlineDatePicker } from '../../DatePicker';

type FormikProps = {
  setFieldValue: Function,
  // … and a bunch of other props not mentioned here.
}

type Props = {
  /** Field name. Also used in setting form state */
  name: string,
  /** formik render props passed via Context API and retrieved via Formik's `connect`. */
  formik: FormikProps,
}

class FormikDatePicker extends React.PureComponent<Props> {
  handleChange = (date: Date) => {
    const { name, formik: { setFieldValue } } = this.props;
    setFieldValue(name, date);
  }

  render() {
    return (
      <InlineDatePicker onDayChange={this.handleChange} />
    );
  }
}

export default connect(FormikDatePicker);

@JonathanTR

This comment has been minimized.

Copy link

commented May 22, 2019

I'm experimenting with Formik in the hope that I can eventually replace ReduxForm with it. For now, I'm using something like this as an adapter around existing inputs to try and mimic the api passed into redux-form inputs:

import React from "react";
import get from "lodash/get";

export const formikAdapter = ({ field, form, ...props }) => ({
  ...props,
  name: field.name,
  input: {
    ...field,
    onBlur: () => form.handleBlur(field.name),
    onChange: (value) => form.setFieldValue(field.name, value),
  },
  meta: {
    touched: get(form.touched, field.name, false),
    dirty: form.dirty,
    error: get(form.errors, field.name, ""),
    valid: form.isValid,
    submitting: form.isSubmitting
  }
})

export const asFormik = (Input) => (props) => 
  <Input {...formikAdapter(props)} />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.