Next.js错误:元素类型无效:应为字符串(对于内置组件)或类/函数(对于复合组件)

5sxhfpxr  于 2023-04-30  发布在  其他
关注(0)|答案(1)|浏览(153)

尝试让Leaflet JS在Next JS中工作,得到一个元素类型无效的错误。这是动态导入我的Map组件的地方。
/components/MapDir/index.js

import dynamic from 'next/dynamic';

const NewMap = dynamic(() => import('./Map'), {
  ssr: false
})

export default NewMap;

/components/MapDir/Map.js
下面是实际的Map组件本身。

import { useEffect } from 'react';
import * as ReactLeaflet from 'react-leaflet';
import 'leaflet/dist/leaflet.css';

import styles from './map.module.css';

import iconMarker2x from 'leaflet/dist/images/marker-icon-2x.png';
import iconMarker from 'leaflet/dist/images/marker-icon.png';
import iconMarkerShadow from 'leaflet/dist/images/marker-shadow.png';

const { MapConsumer, MapContainer } = ReactLeaflet;

const position = [51.505, -0.09]

const Map = ({ children, className, ...rest }) => {

  let mapClassName = styles.map;

  if ( className ) {
    mapClassName = `${mapClassName} ${className}`;
  }

  useEffect(() => {
    delete L.Icon.Default.prototype._getIconUrl
    L.Icon.Default.mergeOptions({
      iconRetinaUrl: iconMarker2x.src,
      iconUrl: iconMarker.src,
      shadowUrl: iconMarkerShadow.src
    })
  }, []);

  return (
    <MapContainer className={mapClassName} {...rest}>
      <MapConsumer>
        {(map) => children(ReactLeaflet, map) }
      </MapConsumer>
    </MapContainer>
  )
}

export default Map;

/pages/stores.js
下面是显示Map组件的页面。

import { useState, useEffect } from 'react';
import Head from 'next/head'
import {
  ApolloClient,
  InMemoryCache,
  gql
} from "@apollo/client";
import center from '@turf/center';
import { points } from '@turf/helpers';

import Layout from "@/components/layout";
import {NewMap} from '@/components/MapDir';

import styles from "@/styles/Mapstyles.module.css"

export default function Stores({ storeLocations }) {
  const [activeStore, setActiveStore] = useState();

  const features = points(storeLocations.map(({ location }) => {
    return [location.latitude, location.longitude]
  }));

  const [defaultLatitude, defaultLongitude] = center(features)?.geometry.coordinates;

  return (
    <Layout>
      <Head>
        <title>Create Next App</title>
        <meta name="description" content="Generated by create next app" />
      </Head>

        <h1>Locations</h1>

        <div className={styles.stores}>

          <div className={styles.storesLocations}>
            <ul className={styles.locations}>
              {storeLocations.map(location => {
                function handleOnClick() {
                  setActiveStore(location.id);
                }
                return (
                  <li key={location.id}>
                    <p className={styles.locationName}>
                      { location.name }
                    </p>
                    <address>
                      { location.address }
                    </address>
                    <p>
                      { location.phoneNumber }
                    </p>
                    <p className={styles.locationDiscovery}>
                      <button onClick={handleOnClick}>
                        View on Map
                      </button>
                      <a href={`https://www.google.com/maps/dir//${location.location.latitude},${location.location.longitude}/@${location.location.latitude},${location.location.longitude},12z/`} target="_blank" rel="noreferrer">
                        Get Directions
                      </a>
                    </p>
                  </li>
                )
              })}

            </ul>
          </div>

          <div className={styles.storesMap}>
            <div className={styles.storesMapContainer}>
              <NewMap className={styles.map} center={[defaultLatitude, defaultLongitude]} zoom={4} scrollWheelZoom={false}>
                {({ TileLayer, Marker, Popup }, map) => {
                  const MapEffect = () => {
                    useEffect(() => {
                      if ( !activeStore ) return;
                      const { location } = storeLocations.find(({ id }) => id === activeStore);
                      map.setView([location.latitude, location.longitude], 14)
                    }, [activeStore])
                    return null;
                  }
                  return (
                    <>
                      <MapEffect />
                      <TileLayer
                        attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
                        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
                      />
                      {storeLocations.map(location => {
                        const { latitude, longitude } = location.location;
                        return (
                          <Marker key={location.id} position={[latitude, longitude]}>
                            <Popup>
                              <p>{ location.name }</p>
                              <p>{ location.address }</p>
                            </Popup>
                          </Marker>
                        )
                      })}

                    </>
                  )
                }}
              </NewMap>
            </div>
          </div>
        </div>
    </Layout>
  )
}

export async function getStaticProps() {
  const client = new ApolloClient({
    uri: 'https://api-us-east-1.graphcms.com/v2/ckzvrda212z1d01za7m8y55rc/master',
    cache: new InMemoryCache()
  });

  const data = await client.query({
    query: gql`
      query PageStores {
        storeLocations {
          address
          id
          name
          phoneNumber
          location {
            latitude
            longitude
          }
        }
      }
    `
  })

  const storeLocations = data.data.storeLocations;

  return {
    props: {
      storeLocations
    }
  }
}
nfeuvbwi

nfeuvbwi1#

我认为这个错误是因为你在/components/MapDir/index.js中做了一个默认的导入,但是你没有调用默认的导入,而是调用了一个上下文中不存在的命名导入。您需要导入这样的组件import NewMap from '@/components/MapDir';,不带括号。

相关问题