hibiken / react-places-autocomplete

React component for Google Maps Places Autocomplete
https://hibiken.github.io/react-places-autocomplete/
MIT License
1.38k stars 388 forks source link

couldn't get it works with formik #244

Closed elzayat closed 4 years ago

madeinspace commented 5 years ago

it is working with formik

abhilashrathod commented 5 years ago

I encountered the same issue while working with formik.

React V 16.5.2 Formik V 1.3.2

this is the minimum reproduction of my code.

class DetailsForm extends Component {
  render() {
    return (
        <Formik
            initialValues={{
              location: '',
            }}
            onSubmit={(values) => {
              this.props.onSubmit(values);
            }}
            validationSchema={object().shape({
              location: string(),
            })}
        >
          {renderProps => {
            const {values, touched, errors, handleChange, handleBlur, handleSubmit} = renderProps;
            return (
                <form className="row" onSubmit={handleSubmit}>
                  <PlacesAutocomplete value={values.location} onChange={handleChange} />
                  <div className="form-group col-12">
                    <button type="submit" className="btn btn-outline-primary">next</button>
                  </div>
                </form>
            )
          }}
        </Formik>
    )
  }
}

The error I got is this...

Failed prop type: The prop 'children' is marked as required in 'PlacesAutocomplete', but its value is 'undefined'. Uncaught TypeError: this.props.children is not a function

Any default value I pass won't work here; like null, undefined and empty object. I saw the example from your repo which provides a blank string as a default value. However this is not working with my case.

Can you please help me out here, thank you!

Kukunin commented 5 years ago

The problem is that <input onChange={handleChange} /> fires handleChange with an event, while <PlacesAutocomplete onChange={handleChange} /> fires with a value. so Formik can't use it as a callback

Kukunin commented 5 years ago

works with formik's setFieldValue: <PlacesAutocomplete onChange={(value) => setFieldValue('city', value)} />

abhilashrathod commented 5 years ago

works with formik's setFieldValue: <PlacesAutocomplete onChange={(value) => setFieldValue('city', value)} />

Thank you for your reply! But; it is still not working for me

elzayat commented 5 years ago

It Works for me

`<Formik initialValues={{ pickup: "" }} onSubmit={(values, actions) => { this.props.getpricelist(values); }} validate={validate} render={({ handleSubmit, setFieldValue, values, errors, touched }) => (

{ return ( { form.setFieldValue("pickup", e); }} /> ); }} />

)} />;`

griffith-icp commented 5 years ago

Hey @Kukunin , is there a way we can get it to fire both an event and the value? Because I'm trying to integrate it with formik and I'm facing the same problems as @abhilashrathod . I'm guessing I'll have to clone the repo and modify the way events are handled myself.

EDIT :

vitorzerbeto commented 5 years ago

The secret to use with Formik is the setFieldValue function.

Into the onChange method, of the <PlacesAutocomplete /> component, you'll need to call setFieldValue to update the formik input value.

This function come from the render({ setFieldValue }) method, provide by the <Formik /> component.

https://jaredpalmer.com/formik/docs/api/formik#setfieldvalue-field-string-value-any-shouldvalidate-boolean-void

On my case, i'm using the autocomplete inside of a <Field /> component. That has {field, form} coming from his render function. The form prop contains the setFieldValue function. Than i pass to the autocomplete.

Something like that:

handleChange({ name, form, search }) {
   form.setFieldValue(name, search);
}

renderPlacesAutocomplete({ field, form }) {

    return (
      <PlacesAutocomplete
        value={field.value}
        onChange={search => {
          this.handleChange({ name: field.name, form, search });
        }}
      >
        {({ getInputProps, getSuggestionItemProps, suggestions }) => {
          const additionalProps = {
            name: field.name,
            className: 'form-input__field',
          };

          const autocompleteInputProps = getInputProps(additionalProps);

          return (
            <div className="autocomplete-root">
              <input {...autocompleteInputProps} />
              <div className="autocomplete-dropdown-container">
                {suggestions.map(suggestion => (
                  <div {...getSuggestionItemProps(suggestion)}>
                    <span>{suggestion.description}</span>
                  </div>
                ))}
              </div>
            </div>
          );
        }}
      </PlacesAutocomplete>
    );
}

render() {
    <Field
        name={name}
        handleBlur={onBlur}
        {...inputProps}
        render={({ field, form }) => this.renderPlacesAutocomplete({ field, form })}
    />
}
RemyMachado commented 4 years ago

In addition of using setFieldValue() given from <Formik />

If you are using useField() or <Field /> as a children of PlacesAutocomplete and you need the field/meta to be available in the parent Component, you can use a second <Field /> with the same name prop to pass them down, see example:

With <Field />

<Field name="same-name"> // they got the same name
    {({ field, meta }) => (
        <div>
            <PlacesAutocomplete
                value={field.value}
                // ...
            >
                <CustomInput name="same-name" /> // they got the same name
            </PlacesAutocomplete>
        </div>
    )}
</Field>    

or

With useField()

const [field, meta] = useField("same-name); // they got the same name

return (
    <div>
        <PlacesAutocomplete
            value={field.value}
            // ...
        >
            <CustomInput name="same-name" /> // they got the same name
        </PlacesAutocomplete>
    </div>
)

Hope it helps.