Доступ к реквизиту для отображения над массивом в React Child? - PullRequest
2 голосов
/ 01 ноября 2019

Работал с реагировать и все еще пытался понять все концепции. Могу воспользоваться помощью, чтобы понять, как я могу заставить это работать. Я хочу передать массив в качестве реквизита для другого реагирующего компонента для отображения. Может кто-то указать, что я здесь делаю не так? Я могу отобразить массив как функцию, но не внутри рендера:

App.js

import React, { Component } from 'react';
import Leaf from './components/Leaf';

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      viewport: {
        height: "100vh",
        width: "100vw",
        latitude: 40.7128,
        longitude: -74.0060,
        zoom: 10
      },
      latitude: 40.7128,
      longitude: -74.0060,
      zoom: 10,
      stations: [],
      selectedStation: null,
      userLocation: {}
    };
  }

  componentDidMount() {
    fetch('https://gbfs.citibikenyc.com/gbfs/en/station_information.json')
    .then(res => res.json())
    .then(res=>
      this.setState({stations: res}))
  }

  checkData=()=>{
    console.log(this.state.stations)
    this.state.stations.data.stations.map(e=>{
      console.log(e)
    })
  }

  render() {

    return (
      <div>
          <button onClick={this.checkData}>click me</button>   
          <Leaf 
            viewport={this.state.viewport}
            stations={this.state.stations}/>
      </div>
    );
  }
}

export default App;

leaf.js

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

class leaf extends Component {

    checkData=()=>{
        this.props.stations.data.stations.map(e=>{
          console.log(e)
        })
      }



    render() {

        const markers = this.props.stations.data.stations.map((station) =>
        <Marker 
          position={[station.lat, station.lon]}
          onClick={this.markerClick.bind(this,station)}>
          <Popup>
          </Popup>
        </Marker>
              );


        const position = [this.props.viewport.latitude, this.props.viewport.longitude]
        //const position = [40.7484, -73.9857]
        return (
            <div>
                <button onClick={this.checkData}>check props</button>
                <Map center={position} zoom={14}>
                    <TileLayer
                        attribution='&amp;copy <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
                        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
                    />
                    {markers}
                    <Marker position={position}>
                        <Popup>
                            A pretty CSS3 popup. <br /> Easily customizable.
                        </Popup>
                    </Marker>
                </Map>  
            </div>
        );
    }
}

export default leaf;

В прошлом я делал что-то вроде:

const Search = ( props ) => {
return (
)
}

Но я пытаюсь понять, как заставить это работать, используя class leaf extends Component. Благодарим за помощь.

Структура данных для справки

    {
    last_updated: 1572631066,
    ttl: 10,
    data: {
    stations: [
    {
    station_id: "237",
    external_id: "66db3c29-0aca-11e7-82f6-3863bb44ef7c",
    name: "E 11 St & 2 Ave",
    short_name: "5746.04",
    lat: 40.73047309,
    lon: -73.98672378,
    region_id: 71,
    rental_methods: [
    "CREDITCARD",
    "KEY"
    ],
    capacity: 39,
    rental_url: "http://app.citibikenyc.com/S6Lr/IBV092JufD?station_id=237",
    electric_bike_surcharge_waiver: false,
    eightd_has_key_dispenser: false,
    eightd_station_services: [
    {
    id: "e73b6bfb-961f-432c-a61b-8e94c42a1fba",
    service_type: "ATTENDED_SERVICE",
    bikes_availability: "UNLIMITED",
    docks_availability: "NONE",
    name: "Valet Service",
    description: "Citi Bike Station Valet attendant service available",
    schedule_description: "",
    link_for_more_info: "https://www.citibikenyc.com/valet"
    }
    ],
    has_kiosk: true
    },
    {
    station_id: "281",
    external_id: "66db5fae-0aca-11e7-82f6-3863bb44ef7c",
    name: "Grand Army Plaza & Central Park S",
    short_name: "6839.10",
    lat: 40.7643971,
    lon: -73.97371465,
    region_id: 71,
    rental_methods: [
    "CREDITCARD",
    "KEY"
    ],
    capacity: 66,
    rental_url: "http://app.citibikenyc.com/S6Lr/IBV092JufD?station_id=281",
    electric_bike_surcharge_waiver: false,
    eightd_has_key_dispenser: true,
    eightd_station_services: [
    {
    id: "32461582-cd1e-4ecf-a5ea-563593fa7009",
    service_type: "ATTENDED_SERVICE",
    bikes_availability: "UNLIMITED",
    docks_availability: "NONE",
    name: "Valet Service",
    description: "Citi Bike Valet Attendant Service Available",
    schedule_description: "",
    link_for_more_info: "https://www.citibikenyc.com/valet"
    }
    ],
    has_kiosk: true
    }
]
}
}

Попытки

Итак, я изменил константные маркеры назеркально отразить conosle.log из checkData:

const markers =  this.props.stations.data.stations.map((station) =>
        <Marker 
          position={[station.lat, station.lon]}
          onClick={this.markerClick.bind(this,station)}>
          <Popup>
          </Popup>
        </Marker>
              );

Я получаю следующую ошибку:

TypeError: Невозможно прочитать свойство 'station' undefined

Когда я удаляю маркерыпеременной и нажмите checkData, обратите внимание, что он не имеет проблем с отображением и консольным журналом объекта:

enter image description here

Ответы [ 2 ]

2 голосов
/ 01 ноября 2019

Я бы дважды проверил, что вы получаете доступ к правильным свойствам данных, как в вашей функции, которую вы вызываете this.props.stations.data.stations.map, но в вашем рендере вы вызываете this.props.stations.data.map, поэтому один из них должен быть неверным.

Кроме того, компоненты класса должны быть PascalCase, то есть с заглавной буквы.

0 голосов
/ 01 ноября 2019

Камило был прав, и мне нужно было убедиться, что данные доступны для рендеринга. Ниже приведен рабочий код:

App.js

//import logo from './logo.svg';
//import './App.css';

import React, { Component } from 'react';
import Leaf from './components/Leaf';

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      viewport: {
        height: "100vh",
        width: "100vw",
        latitude: 40.7128,
        longitude: -74.0060,
        zoom: 10
      },
      latitude: 40.7128,
      longitude: -74.0060,
      zoom: 10,
      stations: [],
      showStations: false,
      selectedStation: null,
      userLocation: {}
    };
  }

  componentDidMount() {
    const request = async()=> {
      await fetch('https://gbfs.citibikenyc.com/gbfs/en/station_information.json')
      .then(res => res.json())
      .then(res=>
        this.setState({stations: res, showStations: true}))
    }
    request();
  }

  checkData=()=>{
    console.log(this.state.stations)
    this.state.stations.data.stations.map(e=>{
      console.log(e)
    })
  }

  render() {

    return (
      <div>
          <button onClick={this.checkData}>click me</button>   
          <Leaf 
            viewport={this.state.viewport}
            stations={this.state.stations}
            showStations={this.state.showStations}/>
      </div>
    );
  }
}

export default App;

Leaf.js

import React, {Component} from 'react';
import { Map, TileLayer, Marker, Popup } from 'react-leaflet';
//import './leaf.css'
//import InfoBox from './InfoBox';
import { Button } from 'react-bootstrap';
//import Search from './Search';
//import Match from './Match';
//import Modal from './Modal';
//import L from 'leaflet';
//import Routing from "./RoutingMachine";
//import { Row, Col, Grid, Container } from 'react-bootstrap';
//import ErrorBoundary from '../ErrorBoundary/ErrorBoundary'



class Leaf extends Component {


    checkData=()=>{
        this.props.stations.data.stations.map(e=>{
          console.log(e)
        })
      }

    render() {

        let markers =null;
        if(this.props.showStations) {
        markers = (
            <div>
            {
            this.props.stations.data.stations.map((station) =>
                <Marker 
                    position={[station.lat, station.lon]}>
                </Marker>
                )
            }
            </div>
        )
        }


        const position = [this.props.viewport.latitude, this.props.viewport.longitude]
        //const position = [40.7484, -73.9857]
        return (
            <div>
                <button onClick={this.checkData}>check props</button>
                <Map center={position} zoom={14}>
                    <TileLayer
                        attribution='&amp;copy <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
                        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
                    />
                      {markers}
                    <Marker position={position}>
                        <Popup>
                            A pretty CSS3 popup. <br /> Easily customizable.
                        </Popup>
                    </Marker>
                </Map>  
            </div>
        );
    }
}

export default Leaf;
...