使用文本字段同时过滤 react-table 和 react-leaflet 标记(在 table 中显示过滤数据,在地图中显示标记)

Filter react-table and react-leaflet marker at the same time using textfield (Show filter data in table and marker in the map)

我是 react-leaflet 的新手。需要很少的帮助来解决我的问题。跟进

我有过滤数据的文本框。我能够过滤 table 中的数据,但无法过滤地图中的数据。 例如:如果我搜索 name: 'VaiBike' 它应该显示在 table 和地图中的标记中。注意:只显示地图中过滤的数据以及table中的数据。其他数据也是如此。

如何更改我的代码,以便我可以同时在 table 中显示标记和数据。

运行代码

import React, { Component } from 'react'
    import { Map, TileLayer, Marker, Popup } from 'react-leaflet'
    import './style.css'
    import 'leaflet/dist/leaflet.css'
    import L from 'leaflet'
    import icon from 'leaflet/dist/images/marker-icon.png'
    import iconShadow from 'leaflet/dist/images/marker-shadow.png'
    import TextField from '@material-ui/core/TextField'
    // Import React Table
    import ReactTable from 'react-table'
    import 'react-table/react-table.css'
    import matchSorter from 'match-sorter'

    var myIcon = L.icon({
      iconUrl:
        'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAApCAYAAADAk4LOAAAFgUlEQVR4Aa1XA5BjWRTN2oW17d3YaZtr2962HUzbDNpjszW24mRt28p47v7zq/bXZtrp/lWnXr337j3nPCe85NcypgSFdugCpW5YoDAMRaIMqRi6aKq5E3YqDQO3qAwjVWrD8Ncq/RBpykd8oZUb/kaJutow8r1aP9II0WmLKLIsJyv1w/kqw9Ch2MYdB++12Onxee/QMwvf4/Dk/Lfp/i4nxTXtOoQ4pW5Aj7wpici1A9erdAN2OH64x8OSP9j3Ft3b7aWkTg/Fm91siTra0f9on5sQr9INejH6CUUUpavjFNq1B+Oadhxmnfa8RfEmN8VNAsQhPqF55xHkMzz3jSmChWU6f7/XZKNH+9+hBLOHYozuKQPxyMPUKkrX/K0uWnfFaJGS1QPRtZsOPtr3NsW0uyh6NNCOkU3Yz+bXbT3I8G3xE5EXLXtCXbbqwCO9zPQYPRTZ5vIDXD7U+w7rFDEoUUf7ibHIR4y6bLVPXrz8JVZEql13trxwue/uDivd3fkWRbS6/IA2bID4uk0UpF1N8qLlbBlXs4Ee7HLTfV1j54APvODnSfOWBqtKVvjgLKzF5YdEk5ewRkGlK0i33Eofffc7HT56jD7/6U+qH3Cx7SBLNntH5YIPvODnyfIXZYRVDPqgHtLs5ABHD3YzLuespb7t79FY34DjMwrVrcTuwlT55YMPvOBnRrJ4VXTdNnYug5ucHLBjEpt30701A3Ts+HEa73u6dT3FNWwflY86eMHPk+Yu+i6pzUpRrW7SNDg5JHR4KapmM5Wv2E8Tfcb1HoqqHMHU+uWDD7zg54mz5/2BSnizi9T1Dg4QQXLToGNCkb6tb1NU+QAlGr1++eADrzhn/u8Q2YZhQVlZ5+CAOtqfbhmaUCS1ezNFVm2imDbPmPng5wmz+gwh+oHDce0eUtQ6OGDIyR0uUhUsoO3vfDmmgOezH0mZN59x7MBi++WDL1g/eEiU3avlidO671bkLfwbw5XV2P8Pzo0ydy4t2/0eu33xYSOMOD8hTf4CrBtGMSoXfPLchX+J0ruSePw3LZeK0juPJbYzrhkH0io7B3k164hiGvawhOKMLkrQLyVpZg8rHFW7E2uHOL888IBPlNZ1FPzstSJM694fWr6RwpvcJK60+0HCILTBzZLFNdtAzJaohze60T8qBzyh5ZuOg5e7uwQppofEmf2++DYvmySqGBuKaicF1blQjhuHdvCIMvp8whTTfZzI7RldpwtSzL+F1+wkdZ2TBOW2gIF88PBTzD/gpeREAMEbxnJcaJHNHrpzji0gQCS6hdkEeYt9DF/2qPcEC8RM28Hwmr3sdNyht00byAut2k3gufWNtgtOEOFGUwcXWNDbdNbpgBGxEvKkOQsxivJx33iow0Vw5S6SVTrpVq11ysA2Rp7gTfPfktc6zhtXBBC+adRLshf6sG2RfHPZ5EAc4sVZ83yCN00Fk/4kggu40ZTvIEm5g24qtU4KjBrx/BTTH8ifVASAG7gKrnWxJDcU7x8X6Ecczhm3o6YicvsLXWfh3Ch1W0k8x0nXF+0fFxgt4phz8QvypiwCCFKMqXCnqXExjq10beH+UUA7+nG6mdG/Pu0f3LgFcGrl2s0kNNjpmoJ9o4B29CMO8dMT4Q5ox8uitF6fqsrJOr8qnwNbRzv6hSnG5wP+64C7h9lp30hKNtKdWjtdkbuPA19nJ7Tz3zR/ibgARbhb4AlhavcBebmTHcFl2fvYEnW0ox9xMxKBS8btJ+KiEbq9zA4RthQXDhPa0T9TEe69gWupwc6uBUphquXgf+/FrIjweHQS4/pduMe5ERUMHUd9xv8ZR98CxkS4F2n3EUrUZ10EYNw7BWm9x1GiPssi3GgiGRDKWRYZfXlON+dfNbM+GgIwYdwAAAAASUVORK5CYII=',
      iconSize: [25, 41],
      iconAnchor: [12.5, 41],
      popupAnchor: [0, -41],
    })
    let DefaultIcon = L.icon({
      iconUrl: icon,
      shadowUrl: iconShadow,
    })

    L.Marker.prototype.options.icon = DefaultIcon

    export default class App extends Component {
      constructor(props) {
        super(props)
        this.state = {
        location: {
          lat: 51.505,
          lng: -0.09,
          filterAll: '',
        },
        bikeData: [],
        haveUsersLocation: false,
        zoom: 3,
      }
      }
      //lifecycle method to get the bike information
      componentDidMount() {
        fetch('https://api.citybik.es/v2/networks')
          .catch(error => {
            console.log(error)
          })
          .then(res => res.json())
          .then(response => {
            const networkData = response.networks
            this.setState({
              bikeData: networkData,
            })
          })
      }
      filterAll = e => {
        const { value } = e.target
        const filterAll = value
        const filtered = [{ id: 'all', value: filterAll }]
        const filterdMap =[{id:'bikeData', value: filterAll}]
        this.setState({ filterAll, filtered ,filterdMap})
      }

      render() {
        const position = [this.state.location.lat, this.state.location.lng]
        const bikeData = this.state.bikeData
        return (
          <div
            style={{
              height: '100vh',
            }}
            id="map"
          >
            <div align="right">
              <form noValidate autoComplete="off">
                <TextField
                  id="row"
                  label="Search Bike"
                  margin="normal"
                  value={this.state.filterAll}
                  onChange={this.filterAll}
                />
              </form>
            </div>
            <Map className="map" center={position} zoom={this.state.zoom}>
              <TileLayer
                attribution="&amp;copy <a href=&quot;http://osm.org/copyright&quot;>OpenStreetMap</a> contributors"
                url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
              />
              {bikeData &&
                bikeData.map(data => {
                  console.log(data)
                  return (
                    <Marker
                      icon={myIcon}
                      key={data.id}
                      position={[data.location.latitude, data.location.longitude]}
                    >
                      <Popup>
                        Name: {data.name} <br />
                        Station Details:{' '}
                        {[data.location.city, data.location.country]}
                      </Popup>
                    </Marker>
                  )
                })}
            </Map>
            <div>
              <ReactTable
                filtered={this.state.filtered}
                defaultFilterMethod={(filter, row) =>
                  String(row[filter.id]) === filter.value
                }
                data={bikeData}
                columns={[
                  {
                    columns: [
                      {
                        Header: ' Name',
                        accessor: 'name',
                        filterAll: true,
                      },

                      {
                        Header: '',
                        id: 'all',
                        width: 0,
                        resizable: false,
                        sortable: false,
                        Filter: () => {},
                        getProps: () => {
                          return {}
                        },
                        filterMethod: (filter, rows) => {
                          const result = matchSorter(rows, filter.value, {
                            keys: ['name'],
                            threshold: matchSorter.rankings.WORD_STARTS_WITH,
                          })

                          return result
                        },
                        filterAll: true,
                      },
                    ],
                  },
                ]}
                defaultPageSize={10}
              />
              <br />
            </div>
          </div>
        )
      }
    }

帮助 运行 代码非常感谢。 提前致谢。

如果我对你的问题的理解正确,你需要对你的代码做一些调整。首先,添加状态以跟踪 "filtered bike data"(即 UI 中用户可见的数据)。你可以通过在你的构造函数中添加这样的东西来做到这一点:

constructor(props) {
    super(props)
    this.state = {
    location: {
      lat: 51.505,
      lng: -0.09,
      filterAll: '',
    },
    bikeData: [],
    filteredBikeData : [], // Add this
    haveUsersLocation: false,
    zoom: 3,
  }
  }

现在,在您 filterAll 所有文本字段更改处理程序中,您需要根据当前字段值更新 filteredBikeData 状态。您可以按以下方式执行此操作:

filterAll = e => {
    const { value } = e.target

    // Get a filtered list of bikes based on original list
    const filteredBikes = this.state.bikeData.filter(bike => {

        // Filter bikes by name. Use toLowerCase to avoid case sensitivity issues
        return bike.name.toLowerCase().indexOf(value.toLowerCase()) !== -1
    })

    const filterAll = value
    const filtered = [{ id: 'all', value: filterAll }]
    const filterdMap =[{id:'bikeData', value: filterAll}]

    // Update state to include filtered bikes array
    this.setState({ filterAll, filtered ,filterdMap, filteredBikes})
}

最后,您需要根据过滤后的自行车数组渲染标记 - 像这样更新您的渲染方法:

{ /* use filteredBikes instead of bikes */
{ this.state.filteredBikes && this.state.filteredBikes.map(data => {
    console.log(data)
    return (
    <Marker
        icon={myIcon}
        key={data.id}
        position={[data.location.latitude, data.location.longitude]}
    >
        <Popup>
        Name: {data.name} <br />
        Station Details:{' '}
        {[data.location.city, data.location.country]}
        </Popup>
    </Marker>
    )
})}

另外,您可能还想将 filteredBikes 的值默认为您从服务器获得的响应,以便用户最初在屏幕上看到一些内容:

componentDidMount() {
    fetch('https://api.citybik.es/v2/networks')
      .catch(error => {
        console.log(error)
      })
      .then(res => res.json())
      .then(response => {
        const networkData = response.networks
        this.setState({
          bikeData: networkData,
          filteredBikeData : networkData // Add this
        })
      })
  }