代码之家  ›  专栏  ›  技术社区  ›  B. Cratty

将数据传递给子组件

  •  0
  • B. Cratty  · 技术社区  · 3 年前

    出身背景

    我在一个网站上工作,我有父组件和子组件。下面的代码片段是一个谷歌地图包装器和一个地图组件。

    密码

    import React, { useEffect, useState, useRef } from "react";
    
    // reactstrap components
    import { Card, Container, Row } from "reactstrap";
    
    // core components
    import Header from "components/Headers/Header.js";
    import LocationSearchInput from "../../components/Places";
    import { useAuthenticator } from "@aws-amplify/ui-react";
    import * as queries from "../../graphql/queries";
    import { API, graphqlOperation } from "aws-amplify";
    import { geocodeByAddress, getLatLng } from "react-places-autocomplete";
    import * as _ from "lodash";
    import { collapseTextChangeRangesAcrossMultipleVersions } from "typescript";
    
    const ChildComponent = (data, loc) => {
      const mapRef = useRef(null);
      console.log("child props", data, loc);
    
      console.log("foo child", loc);
      // THIS WONT WORK BECAUSE WHEN IT FIRST LOADS ITS EMPTY
      // geocodeByAddress(loc[0].HomeLocation)
      //     .then(results => getLatLng(results[0]))
      //     .then(latLng => console.log('Success', latLng))
      //     .catch(error => console.error('Error', error))
    
      useEffect(() => {
    console.log("child mount");
        let google = window.google;
        let map = mapRef.current;
        let lat = "40.748817";
        let lng = "-73.985428";
        const myLatlng = new google.maps.LatLng(lat, lng);
        const mapOptions = {
          zoom: 12,
          center: myLatlng,
          scrollwheel: false,
          zoomControl: true,
          styles: [
            {
              featureType: "administrative",
              elementType: "labels.text.fill",
              stylers: [{ color: "#444444" }],
            },
            {
              featureType: "landscape",
              elementType: "all",
              stylers: [{ color: "#f2f2f2" }],
            },
            {
              featureType: "poi",
              elementType: "all",
              stylers: [{ visibility: "off" }],
            },
            {
              featureType: "road",
              elementType: "all",
              stylers: [{ saturation: -100 }, { lightness: 45 }],
            },
            {
              featureType: "road.highway",
              elementType: "all",
              stylers: [{ visibility: "simplified" }],
            },
            {
              featureType: "road.arterial",
              elementType: "labels.icon",
              stylers: [{ visibility: "off" }],
            },
            {
              featureType: "transit",
              elementType: "all",
              stylers: [{ visibility: "off" }],
            },
            {
              featureType: "water",
              elementType: "all",
              stylers: [{ color: "#5e72e4" }, { visibility: "on" }],
            },
          ],
        };
    
        map = new google.maps.Map(map, mapOptions);
    
        const marker = new google.maps.Marker({
          position: myLatlng,
          map: map,
          animation: google.maps.Animation.DROP,
          title: "Light Bootstrap Dashboard PRO React!",
        });
    
        const contentString =
          '<div class="info-window-content"><h2>Light Bootstrap Dashboard PRO React</h2>' +
          "<p>A premium Admin for React-Bootstrap, Bootstrap, React, and React Hooks.</p></div>";
    
        const infowindow = new google.maps.InfoWindow({
          content: contentString,
        });
    
        google.maps.event.addListener(marker, "click", function () {
          infowindow.open(map, marker);
        });
      }, []);
    
      console.log("child render");
      return (
        <>
          <div
            style={{ height: `600px` }}
            className="map-canvas"
            id="map-canvas"
            ref={mapRef}
          ></div>
        </>
      );
    };
    
    
    
    //PARENT COMPONENT
    const Parent = () => {
      const [foo, setFoo] = useState([]);
    
      const { user, signOut } = useAuthenticator((context) => [context.user]);
      // console.log("user map", user);
    
      const [pin, setPin] = useState([]);
    
      const fetchFoo = async () => {
        console.log(user.attributes.email);
        try {
          const todoData = API.graphql(
            graphqlOperation(queries.listEmployees, {
              filter: {
                Email: {
                  eq: user.attributes.email,
                },
              },
            })
          ).then((response) => {
              console.log("fetch resp", response);
              setFoo(response.data.listEmployees.items);
            })
            .catch((err) => {
              console.log(err);
            });
        } catch (err) {
          console.log("error facing Todos:", err);
        }
      };
      console.log("parent render");
    
      useEffect(() => {
        console.log("parent mount")
        fetchFoo();
      }, []);
    
      var json = [{a: "a", b:"b"}]
    
      return (
        <>
          <Header />
          {/* Page content */}
          {/* {foo} */}
          <Container className="mt--7" fluid>
            <Row>
              <div className="col">
                {/* <LocationSearchInput /> */}
              </div>
            </Row>
            <Row>
              <div className="col">
                <Card className="shadow border-0">
                  {/* <> */}
                  <ChildComponent data={json} loc={{foo}}/>
                  {/* </> */}
                </Card>
              </div>
            </Row>
          </Container>
        </>
      );
    };
    
    export default Parent;
    

    输出

    console output #1 console output #2

    问题

    子组件首次读取数据时为空,但在第二次加载时填充。我已经尝试过调整useEffect以使其工作,但唯一的区别是,如果移除空数组,它将执行无限循环。

    0 回复  |  直到 3 年前
        1
  •  1
  •   Ryan Le    3 年前

    有几件事你需要修改,使其生效

    首先,移除组件道具中的额外支架:

    <MapWrapper data={json} loc={foo}/>
    

    其次,因为它们是道具,所以您需要在括号内访问它们:

    const MapWrapper = ({data, loc}) => {
    ...
    

    对于初始加载中的空数据,我建议您在发出任何请求之前检查空数组。

    if (foo.length > 0) {
       // Do fetch
    }