ReduxForm:从子组件添加地图输入

时间:2017-11-09 12:01:35

标签: javascript reactjs redux redux-form

我有一个Redux表单组件,其中包含一个名为PlotMap的Google Maps子组件。子组件将映射输入作为回调中的对象传递回来。我希望在提交时将此地图输入对象包含在表单数据中。我怎么做?我是否使用隐藏的字段? Redux Form的奇妙工作对我来说是不透明的,所以我不确定在哪里附加对象。

PlotForm组件:

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Field, reduxForm } from 'redux-form';
import * as actions from '../../actions';
import { Link } from 'react-router';
import PlotMap from './plotMap';

const renderField = ({
    input,
    label,
    type,
    meta: { touched, error, warning }
}) => (
    <fieldset className="form-group">
        <label htmlFor={input.name}>{label}</label>
        <input className="form-control" {...input} type={type} />
        {touched && error && <span className="text-danger">{error}</span>}
    </fieldset>
);

class PlotForm extends Component {
    constructor(props) {
        super(props);
        this.handleFormSubmit = this.handleFormSubmit.bind(this);
    }

    handleFormSubmit(props) {
        this.props.addPlot(props);
    }

    render() {
        const { handleSubmit } = this.props;
        const user = JSON.parse(localStorage.getItem('user'));
        return (
            <div className="form-container text-center">
                <form onSubmit={handleSubmit(this.handleFormSubmit.bind(this))}>
                    <Field
                        name="name"
                        component={renderField}
                        type="text"
                        label="Plot Name"
                    />
                    {user &&
                        user.role === 3 && (
                            <Field
                                name="company"
                                component={renderField}
                                type="text"
                                label="Company"
                            />
                        )}
                    <Field
                        name="grower"
                        component={renderField}
                        type="text"
                        label="Grower"
                    />
                    <Field
                        name="variety"
                        component={renderField}
                        type="text"
                        label="Variety"
                    />
                    <Field
                        name="variety2"
                        component={renderField}
                        type="text"
                        label="Variety 2"
                    />
                    <Field
                        name="planted"
                        component={renderField}
                        type="date"
                        label="Date Planted"
                    />
                    <hr />
                    <PlotMap getGeoJSON={GeoJSON => console.log(GeoJSON)} />
                    <div className="form-group">
                        <span>
                            <label>&nbsp;</label>
                            <button type="submit" className="btn btn-primary">
                                Add Plot
                            </button>
                        </span>
                    </div>
                </form>
                <hr />
                <div>
                    {this.props.errorMessage &&
                        this.props.errorMessage.plots && (
                            <div className="error-container">
                                Oops! {this.props.errorMessage.plots}
                            </div>
                        )}
                </div>
            </div>
        );
    }
}

function mapStateToProps(state) {
    return {
        errorMessage: state.plots.error
    };
}

PlotForm = reduxForm({ form: 'plot', validate })(PlotForm);
export default connect(mapStateToProps, actions)(PlotForm);

PlotMap组件:

import React, { Component } from 'react';
const { compose, withProps } = require('recompose');
const { withScriptjs, withGoogleMap, GoogleMap } = require('react-google-maps');
const {
    DrawingManager
} = require('react-google-maps/lib/components/drawing/DrawingManager');

const editTrack = polygon => {
    let GeoJSON = {
        type: 'Feature',
        geometry: {
            type: 'Polygon',
            coordinates: []
        },
        properties: {}
    };
    for (let point of polygon.getPath().getArray()) {
        GeoJSON.geometry.coordinates.push([point.lng(), point.lat()]);
    }
    return GeoJSON;
};

const PlotMap = compose(
    withProps({
        googleMapURL:
            'https://maps.googleapis.com/maps/api/js?key=myKey&v=3.exp&libraries=geometry,drawing,places',
        loadingElement: <div style={{ height: `100%` }} />,
        containerElement: <div style={{ height: `400px` }} />,
        mapElement: <div style={{ height: `100%` }} />
    }),
    withScriptjs,
    withGoogleMap
)(props => (
    <GoogleMap
        defaultZoom={8}
        defaultCenter={new google.maps.LatLng(32.095, 35.398)}>
        <DrawingManager
            onPolygonComplete={polygon => {
                polygon.setEditable(true);
                props.getGeoJSON(editTrack(polygon));
                google.maps.event.addListener(polygon.getPath(), 'insert_at', function(
                    index,
                    obj
                ) {
                    props.getGeoJSON(editTrack(polygon));
                });
                google.maps.event.addListener(polygon.getPath(), 'set_at', function(
                    index,
                    obj
                ) {
                    props.getGeoJSON(editTrack(polygon));
                });
            }}
            defaultDrawingMode={google.maps.drawing.OverlayType.POLYGON}
            defaultOptions={{
                drawingControl: true,
                drawingControlOptions: {
                    style: google.maps.MapTypeControlStyle.HORIZONTAL_BAR,
                    position: google.maps.ControlPosition.TOP_CENTER,
                    drawingModes: [google.maps.drawing.OverlayType.POLYGON]
                }
            }}
        />
    </GoogleMap>
));

export default PlotMap;

1 个答案:

答案 0 :(得分:2)

如您所知,您可以将无状态函数(&#34; renderField&#34;)作为component道具传递给Field。您可以将PlotMap包装在函数中,并仅将onChange处理程序连接到getGeoJSON

onChange方法描述为:

  

每当触发onChange事件时将调用的回调   来自潜在的输入。

此回调通知redux-form字段内容已更改,并更新redux存储。您可以手动调用它并传递数据,而不是使用onChange事件调用它。

示例redux-form(未经测试):

<Field name="plotMap" component={({ input }) => (
  <PlotMap getGeoJSON={input.onChange} />
)}/>