javascriptreactjsredux-formreact-redux-form

How to pass values from on component to Redux form


I am using Redux form for form in React.js and my form was and I have a custom google map component I want to bind lat and long to my form

form

import React from 'react';
import { Field, reduxForm } from 'redux-form';
const SimpleForm = props => {
  const { handleSubmit, pristine, reset, submitting } = props;
  return (
    <form onSubmit={handleSubmit}>
      <div className="position-relative form-group">
        <label>First Name</label>
        <div>
          <Field
            name="firstName"
            component="input"
            type="text"
            placeholder="First Name"
            className="form-control"
          />
        </div>
      </div>
<Field name = 'eventLocation'
        component = {MyParentComponentWrapper} />
</form>
  );
};
export default reduxForm({
  form: 'simple', // a unique identifier for this form
})(SimpleForm);

and my MyParentComponentWrapper code was

import React from 'react';
import { compose, withProps, lifecycle } from 'recompose';
import { withScriptjs, withGoogleMap, GoogleMap, Marker } from 'react-google-maps';

const MyMapComponent = compose(
    withProps({
        googleMapURL:
            'https://maps.googleapis.com/maps/api/js?key=AIzaSyCYSleVFeEf3RR8NlBy2_PzHECzPFFdEP0&libraries=geometry,drawing,places',
        loadingElement: <div style={{ height: `100%` }} />,
        containerElement: <div style={{ height: `400px` }} />,
        mapElement: <div style={{ height: `100%` }} />,
    }),
    lifecycle({
        componentWillMount() {
            const refs = {};

            this.setState({
                position: null,
                onMarkerMounted: ref => {
                    refs.marker = ref;
                },

                onPositionChanged: () => {
                    const position = refs.marker.getPosition();
                    console.log(position.toString());
                },
            });
        },
    }),
    withScriptjs,
    withGoogleMap
)(props => (
    <GoogleMap defaultZoom={8} defaultCenter={{ lat: -34.397, lng: 150.644 }}>
        {props.isMarkerShown && (
            <Marker
                position={{ lat: -34.397, lng: 150.644 }}
                draggable={true}
                ref={props.onMarkerMounted}
                onPositionChanged={props.onPositionChanged}
            />
        )}
    </GoogleMap>
));

class MyParentComponentWrapper extends React.PureComponent {
    state = {
        isMarkerShown: false,
    };

    render() {
        return (
            <div>
                <MyMapComponent isMarkerShown={true} />
            </div>
        );
    }
}

export default MyParentComponentWrapper;

this component will console.log the lat and long values when user drag the marker

How to pass the console.log value to redux-form?

Can anyone please suggest a way to do so?


Solution

  • Here is a codesandbox of your app using a redux-form. Notice that after setting up the form in latLngForm.js, I use connect in your map container to dispatch reduxForm's change action when your marker is moved. This is what updates the store.

    I also pass position in as a prop to <MyMapComponent /> to set the position of your marker. This means that your marker's position is always based off of the form's values, and that moving the map's markers manually changes the form's value. This will allow you to set the position manually via the fields, or by dragging and dropping the marker.

    mapStateToProps in the <MyMapComponent /> is the important piece here. redux-form automatically stores the values in the state for us, this is where we retrieve it.

    Notice these lines at the top of the file:

    import { change, formValueSelector } from "redux-form";
    ...
    const formSelector = formValueSelector("form");
    

    This sets up our form selector. "form" being the identifier for the form. Now, to retrieve these values from our state, we do:

    const mapStateToProps = (state) => ({
        position: {
            lat: formSelector(state, 'lat'),
            lng: formSelector(state, 'lng') // The key here is the name you passed into the field.
        }
    });
    

    Then we use connect to actually connect the component to the store:

    connect(mapStateToProps)(MyMapComponent);
    

    Redux does its magic and now our fields are available via this.props.position in our component!