javascript - react-google-maps 在用户提交后呈现标记

标签 javascript forms reactjs redux react-google-maps

这里是 React/Redux 新手。我有一个表单输入,允许用户输入医生问题。它通过 Redux 操作从服务器返回医生列表,并在 map 上显示医生列表和每个医生位置的标记 (react-google-maps)。

当我单击提交时,将显示正确问题的医生列表, map 在那里,但没有标记。只有在提交表单后,我才能在 map 上显示标记,然后单击列表中的医生以显示其详细信息。

想要:输入医生问题并在用户点击提交时在 map 上呈现医生列表和标记。然后,选择一位医生以查看其详细信息页面(这是另一个问题,路由到动态详细信息页面)。

我想,我需要使用生命周期方法,但不确定如何实现它。或者,有没有更好的方法来使用 Redux 来处理这个问题?

医生组件:

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

import DoctorSearchForm from '../../containers/doctors/DoctorSearchForm';
import DoctorList from './DoctorList';
import Map from '../maps/Map';


class Doctors extends Component {

  constructor(props) {
    super(props);
    this.state = {
      markers: [],
      isMarkerShown: false
    }
  }

  componentDidMount() {
    this.getMarkers();
  }

  getMarkers = () => {
    let practices = this.props.doctors.map(function(doctor, index) {
      return {
        title: doctor.profile.first_name + ' ' + doctor.profile.last_name,
        location: {
          lat: doctor.practices[0].visit_address.lat,
          lng: doctor.practices[0].visit_address.lon
        }
      }
    });
    this.setState({ markers: practices, isMarkerShown: true });
  }

  render() {
    const { doctors, match } = this.props;

    return (
      <div>
        <DoctorSearchForm getMarkers={this.getMarkers} />
        <div className="row">
          <div className="col-md-4">
            <DoctorList doctors={doctors} match={match} />
          </div>
          <div className="col-md-8">
            <Map
              isMarkerShown={this.state.isMarkerShown}
              center={{ lat: 45.6318,lng: -122.6716 }}
              zoom={12}
              markers={this.state.markers}
              />
          </div>
        </div>
      </div>
    );
  }
}

Doctors.propTypes = {
  doctors: PropTypes.array.isRequired,
  match: PropTypes.object.isRequired
}

export default Doctors;

DoctorList 组件:

import React from "react";
import { Route } from 'react-router-dom';

import DoctorItem from './DoctorItem';
import DoctorView from './DoctorView';


class DoctorList extends React.Component {
  render() {
    const { doctors, match } = this.props;
    const linkList = doctors.map((doctor, index) => {
      return (
        <DoctorItem doctor={doctor} match={match} key={index} />
      );
    });

    return (
      <div>
        <h3>DoctorList</h3>
        <ul>{linkList}</ul>
        <Route path={`${match.url}/:name`}
          render={ (props) => <DoctorView data= {this.props.doctors} {...props} />}
          />
        </div>
      );
  }
}

export default DoctorList;

DoctorItem 组件:

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Link, Route } from 'react-router-dom';

import DoctorView from './DoctorView';


const DoctorItem = (props) => {
  const { doctor, match } = props;
    return (
      <li>
        <Link to={{ pathname: `${match.url}/${doctor.profile.first_name}-${doctor.profile.last_name}` }}>
          {doctor.profile.first_name} {doctor.profile.last_name}
        </Link>
      </li>
    )
  }

  DoctorItem.propTypes = {
    doctor: PropTypes.object.isRequired,
  };

  export default DoctorItem;

DoctorView 组件:

import React from 'react';


const DoctorView = ({ data, match }) => {
  const doctor = data.find(p => `${p.profile.first_name}-${p.profile.last_name}` === match.params.name);


  let doctorData;

  if (doctor) {
    const mappedSpecialties = Object.entries(doctor.specialties).map(([index, specialty]) => {
      return <li key={index} id={index}>{specialty.description}</li>;
      });
      doctorData =
      <div>
        <h5><strong>{doctor.profile.first_name} {doctor.profile.last_name}</strong> - {doctor.profile.title}</h5>
        <img src={doctor.profile.image_url} alt={"Dr." + doctor.profile.first_name + " " + doctor.profile.last_name} />
        <ul>{mappedSpecialties}</ul>
        <p>{doctor.profile.bio}</p>
      </div>;
    }
    return (
      <div>
        {doctorData}
      </div>
    )
  }

  export default DoctorView;

map 组件:

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { withScriptjs, withGoogleMap, GoogleMap, Marker } from 'react-google-maps';
import { compose, withProps } from "recompose";


export default Map = compose(
  withProps({
    googleMapURL:
      "https://maps.googleapis.com/maps/api/js?key={MY_KEY}&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={9} defaultCenter={{ lat: 45.6318,lng: -122.6716 }}>
    {props.markers.map((doctor, index) => {
          const marker = {
            position: { lat: doctor.location.lat, lng: doctor.location.lng },
            title: doctor.title
          }
          return <Marker key={index} {...marker} />;
        })}
  </GoogleMap>
));

我花了几天时间尝试和寻找答案,但没有成功。任何帮助将不胜感激!

最佳答案

就像你在组件挂载时计算标记一样,当你收到新的 Prop 时你需要重新计算你的标记:

componentWillReceiveProps(nextProps) {
   this.getMarkers(nextProps);
}

这将要求您更改您的 getMarkers签名一点,以便它可以接受一个参数并使用它而不是 this.props在你的map操作:

getMarkers = (props = this.props) => {
  let practices = props.doctors.map(function(doctor, index) {
    return {
      title: doctor.profile.first_name + ' ' + doctor.profile.last_name,
      location: {
        lat: doctor.practices[0].visit_address.lat,
        lng: doctor.practices[0].visit_address.lon
      }
    }
  });
  this.setState({ markers: practices, isMarkerShown: true });
}

假设您正在调用 getMarkers()在你的DoctorSearchForm组件,你可以删除它,因为它会在接收新 Prop 时自动更新标记——或者你可以完全绕过状态,只是在 render 中即时计算它。基于传入props .

关于javascript - react-google-maps 在用户提交后呈现标记,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48635078/

相关文章:

javascript - 按下审阅按钮时的 JQuery 预览表单

javascript - 是否可以在不渲染 HTML 的情况下使用 React?

javascript - 如何在 Mobx-State-Tree 中拥有可为空的字符串值

reactjs - 为 nextjs 项目设置关键 css 和删除不需要的 CSS 的正确方法

javascript - 在 typescript 中使用命名空间时找不到名称错误

javascript - V8JS 时区测试失败

javascript - 如何像梯形一样对齐文本?

forms - 隐藏的自定义类型实体总是不通过类

jquery - 如何使用 jquery 验证进行提交确认?

javascript - Ajax调用: Monitor if it is taking long time