.map()仅显示数组中的最后一项

时间:2018-09-28 08:51:58

标签: json reactjs api leaflet react-leaflet

我想使用Citybik.es API(http://api.citybik.es/)在传单地图上显示数据。

目前,该代码仅在render函数中显示bikeData.map()中的最后一项。

enter image description here

console.log(data)显示bikeData.map()中的每个迭代项,但仅显示最后一个项。

enter image description here

我正在寻找这样的东西。

我想念什么?

响应看起来像这样:

{
  "networks": [
  {
    "company": [
      "Bike U Sp. z o.o."
    ], 
    "href": "/v2/networks/bbbike", 
    "id": "bbbike", 
    "location": {
      "city": "Bielsko-Bia\u0142a", 
      "country": "PL", 
      "latitude": 49.8225, 
      "longitude": 19.044444
    }, 
    "name": "BBBike"
  }, 
  {
    "company": [
      "PBSC", 
      "Alta Bicycle Share, Inc"
    ], 
    "href": "/v2/networks/melbourne-bike-share", 
    "id": "melbourne-bike-share", 
    "location": {
      "city": "Melbourne", 
      "country": "AU", 
      "latitude": -37.814107, 
      "longitude": 144.96328
    }, 
    "name": "Melbourne Bike Share"
  }
}

这是JavaScript:

import React, { Component } from 'react';
import L from 'leaflet';
import { Map, TileLayer, Marker, Popup } from 'react-leaflet';

// code for map marker icon
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]
});

class App extends Component {
    state = {
        location: {
            lat: 51.505,
            lng: -0.09,
        },
        bikeData: [],
        zoom: 2,
    }

    //lifecycle method to get the bike information
    componentDidMount() {

        fetch('https://api.citybik.es/v2/networks')
            .then(res => res.json())
            .then(response => {
                const networkData = response.networks;
                networkData.map((data) => {
                    console.log(data)
                    this.setState({
                        bikeData: [data]
                    });
                })
            })
    }


    render() {
        const position = [this.state.location.lat, this.state.location.lng]
        const bikeData = this.state.bikeData;
        return (
            <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>
        )
    }
}

ReactDOM.render(<App/>,
    document.getElementById('root')
);

3 个答案:

答案 0 :(得分:3)

您反复覆盖bikeData状态项:

fetch('https://api.citybik.es/v2/networks')
     .then(res => res.json())
     .then(response => {
         const networkData = response.networks;
         networkData.map((data) => {
             console.log(data)
             this.setState({          // ***
                 bikeData: [data]     // *** Here
             });                      // ***
         })
     })

目前尚不清楚为什么在此使用map;当然,如果您不想从回调中返回值并且不使用map创建的数组,那么map是错误的工具。

我不能肯定地说,但似乎您只想直接使用networkData

fetch('https://api.citybik.es/v2/networks')
     .then(res => res.json())
     .then(response => {
         const networkData = response.networks;
         this.setState({bikeData: networkData});
     })

请注意,我假设您要对结果进行覆盖 bikeData,而不是对其进行添加

或者,如果您希望以某种方式转换该数据,则可以使用map结果

fetch('https://api.citybik.es/v2/networks')
     .then(res => res.json())
     .then(response => {
         const networkData = response.networks;
         this.setState({
             bikeData: networkData.map((data) => {
                 return /*...do something to data...*/;
             })
         });
     })

(假设相同)

添加到 bikeData,您需要使用setState的回调形式:

         this.setState(({bikeData}) => ({
             bikeData: [...bikeData, ...networkData.map((data) => {
                 return /*...do something to data...*/;
             })]
         });

还请注意,您在fetch通话中遇到了错误(您并不孤单,有很多人{strong> 这样做I wrote it up on my anemic little blog):您没有没有选中res.ok

fetch('https://api.citybik.es/v2/networks')
     .then(res => {                        // ***
         if (!res.ok) {                    // ***
             throw new Error(res.status);  // ***
         }                                 // ***
     })                                    // ***
     .then(res => res.json())
     .then(response => {
         // ...

答案 1 :(得分:1)

尝试一下:

 componentDidMount() {
    fetch('https://api.citybik.es/v2/networks')
        .then(res => res.json())
        .then(response => {
            const networkData = response.networks; //which is currently an array
             this.setState({
                 bikeData: networkData 
             });
        })
 }

答案 2 :(得分:0)

不建议您在循环内执行setState。循环外的setState也是如此。同样,将数据推入数组的方式也不正确。请尝试以下解决方案

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output encoding='UTF-8' indent='yes' method='xml'/>

<xsl:template match="@* | node()">
    <xsl:copy>
        <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="*[local-name() = 'MainTag']">
    <xsl:element name="ns0:{local-name()}" namespace="http://xyz987.com">
        <xsl:apply-templates select="@* | node()" />
    </xsl:element>
</xsl:template>

<xsl:template match="*[local-name() = 'DifferentTag']">
    <xsl:element name="ns0:{local-name()}" namespace="http://QWR.com">
        <xsl:apply-templates select="@* | node()" />
    </xsl:element>
</xsl:template>

<xsl:template match="*/*">
    <xsl:element name="{local-name()}">
        <xsl:apply-templates select="@* | node()" />
    </xsl:element>
</xsl:template>
</xsl:stylesheet>