私はReact.jsのフォームにReduxフォームを使用していますが、フォームはlatとlongをフォームにバインドしたいカスタムのgoogle mapコンポーネントを持っています
フォーム
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);
そして私のMyParentComponentWrapperコードは
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;
このコンポーネントは、ユーザーがマーカーをドラッグすると、lat。とlongの値をconsole.logに記録します
console.log
値をredux-formに渡す方法は?
誰かがそうする方法を提案できますか?
ここ は、redux-form
を使用するアプリのコードサンドボックスです。 latLngForm.js
でフォームを設定した後、マップコンテナーでconnect
を使用して、マーカーが移動したときにdispatch
reduxFormのchange
アクションを実行します。これがストアを更新するものです。
また、position
をprop
として<MyMapComponent />
に渡して、マーカーの位置を設定します。つまり、マーカーの位置は常にフォームの値に基づいており、マップのマーカーを移動するとフォームの値が手動で変更されます。これにより、フィールドを使用して手動で、またはマーカーをドラッグアンドドロップして位置を設定できます。
<MyMapComponent />
のmapStateToProps
は、ここで重要な部分です。 redux-form
は自動的に値を状態に格納します。これが取得する場所です。
ファイルの上部にある次の行に注意してください。
import { change, formValueSelector } from "redux-form";
...
const formSelector = formValueSelector("form");
これでフォームセレクターが設定されました。 "form"
はフォームの識別子です。次に、これらの値を状態から取得するには、次のようにします。
const mapStateToProps = (state) => ({
position: {
lat: formSelector(state, 'lat'),
lng: formSelector(state, 'lng') // The key here is the name you passed into the field.
}
});
次に、connect
を使用してコンポーネントを実際にストアに接続します。
connect(mapStateToProps)(MyMapComponent);
Reduxはその魔法を実行し、コンポーネントのthis.props.position
を介してフィールドを使用できるようになりました。
ここ は、サンドボックスから分岐した私の実用的なソリューションです。
マーカーの位置が変わるたびに発生するMyParentComponentWrapper
コンポーネントにコールバックを追加しました。フォームでは、コールバックをリッスンし、position
フィールドにMyParentComponentWrapper
から受け取った値を設定します。
私はコンポーネントをできるだけシンプルに保ち、connect
を介してコンポーネントをredux状態に接続しないようにします。 MyParentComponentWrapper
は、この値がどのように/どこで使用されるかを意識せずに、値が変更されるたびにchange
イベントのみを発生させる入力フィールドと考えてください。
この場合、MyParentComponentWrapper
はマーカーを表示し、マーカーの位置が変わるたびにコールバックを呼び出します。この位置を適切に処理するのはフォームコンポーネントです。
これが、コールバックを使用してフォームのレンダリングを変更した方法です。
<MyParentComponentWrapper setPosition={onPositionSet} />
フォームコンポーネントのコールバックは次のとおりです。
const onPositionSet = (position) => {
props.change("position", position);
}
change
関数は、redux-form
でラップしたときにコンポーネントの小道具に追加されました