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

redux-form .change() has no effect on <Geosuggest /> #275

Open
fetzig opened this issue Feb 8, 2017 · 7 comments
Open

redux-form .change() has no effect on <Geosuggest /> #275

fetzig opened this issue Feb 8, 2017 · 7 comments

Comments

@fetzig
Copy link

fetzig commented Feb 8, 2017

Short description

Use <Geosuggest /> in redux-form

Expected results

<Geosuggest /> should work same way as outside redux-form

redux-form should be able to aggregate/validate/manipulate/... value of <Geosuggest />

Actual results

Everything works just great, except one very central problem.

redux-form can't manipulate the value of <Geosuggest /> at all. Resulting in even bigger problems when implementing in FieldArray.

Reproduction steps

Using this implementation shows redux-form updates the input.value as expected. But Geosuggest doesn't update.

import Geosuggest from 'react-geosuggest';
import { Field } from 'redux-form';

const CustomGeosuggest = ({ input, label, meta: { touched, error }, ...custom }) => (
    <div>
        <pre>{JSON.stringify(input, null, 2)}</pre>
        <Geosuggest name={input.name} value={input.value} {...custom} />
        {touched && error && <span>{error}</span>}
    </div>
)

<Field
    component={CustomGeosuggest}
    className="ui search"
    name="location_name"
    placeholder="Location"
    onSuggestSelect={onSuggestSelect}
    />

Additional Information

IMHO it's not totally clear if this is a bug or no bug.

Anyways: I'm sure there is a proper way to do this, or at least a workaround. Infos about those are highly appreciated.

@schwermer
Copy link

schwermer commented Apr 10, 2017

Here is a wrapper class that allows react-geosuggest to be used with redux-form:

export class renderGeosuggest extends React.Component {
  componentWillReceiveProps(nextProps) {
    if(this.props.input.value != nextProps.input.value) {
      this.refs.geosuggest.update(nextProps.input.value)
    }
  }
  render() {
    const {input, label, ...custom} = this.props
    return (
        <div>
	  <label>{label}</label>
	  <Geosuggest 
	    ref="geosuggest"
	    initialValue={ input.value }
	    onSuggestSelect={ (suggest) => input.onChange(suggest.label) }
	    {...custom}
	  />
	</div>
    )
  }
}

It would be nice if the next major version of this library used the value/onChange pattern that most form related React components have adopted.

@ro-ka
Copy link
Contributor

ro-ka commented Jun 9, 2017

We’ll keep that in mind for a new major. Feel free to submit a PR if you find a way to implement it without breaking! Hope the workaround works.

@danadn
Copy link

danadn commented Sep 7, 2017

Just in case someone wants to load google maps lib async:

import React from 'react';
import withScriptjs from "react-google-maps/lib/async/withScriptjs";
import Geosuggest from 'react-geosuggest';

const googleMapURL="https://maps.googleapis.com/maps/api/js?v=3.27&libraries=places,geometry&key=YOUR_API_KEY"

class RenderGeosuggest extends React.Component {
  componentWillReceiveProps(nextProps) {
    if(this.props.input.value != nextProps.input.value) {
      this.refs.geosuggest.update(nextProps.input.value)
    }
  }
  render() {
    const {input, label, ...custom} = this.props
    return (
        <div>
      <label>{label}</label>
      <Geosuggest 
        ref="geosuggest"
        initialValue={ input.value }
        onSuggestSelect={ (suggest) => input.onChange(suggest.label) }
        {...custom}
      />
    </div>
    )
  }
}

export const renderGeosuggestAsync = withScriptjs(
   props => (<RenderGeosuggest {...props}/>)
);

And then just:

<Field name="address" component={ renderGeosuggestAsync } 
   googleMapURL = {googleMapURL}
   loadingElement={
       <div style={{ height: `100%` }}>
              "Loading library..."
       </div>} 
/>

@amackintosh
Copy link

amackintosh commented Dec 2, 2017

I don't want to get too excited, but this is working for me currently with Geosuggest and Redux-Form V7.2

import React, { Component } from 'react'
import PropTypes from 'prop-types'
import Geosuggest from 'react-geosuggest'

class CreateGeoSuggest extends Component {
  render() {
    const {
      input,
      meta: { touched, error },
      name,
      label,
      required,
      placeholder,
    } = this.props
    const maybeHasValue = (input.value)
      ? 'edit_filled'
      : 'edit_empty'
    const maybeHasError = (touched && error)
      ? 'form-text-input error'
      : `form-text-input normal ${maybeHasValue}`
    return (
      <div className="edit_rowcontainer">
        <label className="edit_row" htmlFor={name}>
          <div className="edit_row-label">
            {label}
            {required && <span className="edit_asterisk">*</span>}
          </div>
          <div className="edit_row-item">
            <Geosuggest
              ref={el => this._geoSuggest = el} // eslint-disable-line
              placeholder={placeholder}
              inputClassName={maybeHasError}
              name={name}
              initialValue={input.value}
              onSuggestSelect={(suggest) => {
                if (!suggest) return input.onChange(null)
                return input.onChange(suggest.label)
              }}
              {...input}
            />
          </div>
        </label>
        {touched && (error && <span className="edit_required">{error}</span>)}
      </div>
    )
  }
}

Called like this:

<Field
  label=""
  component={CreateGeoSuggest}
  name="person_location"
  placeholder="Enter Location"
/>

The above code works correctly including with Redux-Form sync validation.

Special thanks to the wizards above me in this thread.

Pay special attention to my onSuggestSelect modification. If you don't do that, the code will detonate if you backspace the field to empty because suggest.label will be undefined. My mod allows it to set the field to null, which will do a Redux-Form action @@redux-form/CHANGE with payload: ""

@amackintosh
Copy link

amackintosh commented Dec 2, 2017

Ok, confirmed. The above code works nice for both create and edit scenarios.

@Ezekiah
Copy link

Ezekiah commented Dec 19, 2017

Hello,
I would like to know how can I store the full adresse object in the redux form value and only display the label on the field.
Thanks

@dmcclurealinta
Copy link

@Ezekiah use @amackintosh example but change return input.onChange(suggest.label) to input.onChange(suggest.gmaps) and the entire object will be passed into your redux-form store but the label and view be different.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants