首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在react v3中扩展v3组件?

如何在react v3中扩展v3组件?
EN

Stack Overflow用户
提问于 2021-01-11 08:55:23
回答 2查看 2.7K关注 0票数 3

我正在尝试在“react传单”TileLayer中扩展v3组件。有必要重写此函数以提供自定义的平铺URL命名方案。我需要的一个例子,用基本传单写成:

代码语言:javascript
复制
function initMap() {
    L.TileLayer.WebGis = L.TileLayer.extend({

        initialize: function (url, options) {
            options = L.setOptions(this, options);
            if (options.detectRetina && L.Browser.retina && options.maxZoom > 0) {
                options.tileSize = Math.floor(options.tileSize / 2);
                options.zoomOffset++;
                if (options.minZoom > 0) {
                    options.minZoom--;
                }
                this.options.maxZoom--;
            }
            if (options.bounds) {
                options.bounds = L.latLngBounds(options.bounds);
            }
            this._url = url + "/gis_render/{x}_{y}_{z}/" + options.userId + "/tile.png";
            var subdomains = this.options.subdomains;
            if (typeof subdomains === 'string') {
                this.options.subdomains = subdomains.split('');
            }
        },

        getTileUrl: function (tilePoint) {
            return L.Util.template(this._url, L.extend({
                s: this._getSubdomain(tilePoint),
                z: 17 - this._map._zoom,
                x: tilePoint.x,
                y: tilePoint.y
            }, this.options));
        }
    });

    L.tileLayer.webGis = function (url, options) {
        return new L.TileLayer.WebGis(url, options);
    };

    // create a map in the "map" div, set the view to a given place and zoom
    var map = L.map('map').setView([53.9, 27.55], 10);

    // add an Gurtam Maps tile layer
    L.tileLayer.webGis(wialon.core.Session.getInstance().getBaseGisUrl('render'), {
        attribution: 'Gurtam Maps',
        minZoom: 4,
        userId: wialon.core.Session.getInstance().getCurrUser().getId()
    }).addTo(map);

}

如果我只是将Gurtam映射的url写到TileLayer组件的“url”支柱上,那么我的地图就不能正确显示(缩放和平铺错误)。

我不知道该用什么来做正确的显示:

  1. 使用'useRef‘钩子获取当前的TileLayer实例并对其进行扩展。
  2. 使用一些钩子(可能是createElementHook)从包‘react传单/核心’,并创建我自己的自定义组件
  3. 或者别的什么

如有任何解释,我将不胜感激。

EN

回答 2

Stack Overflow用户

发布于 2021-01-14 05:25:00

听起来像是在react-leaflet v3中创建一个自定义组件。如果你不太熟悉反应传单,这可能会令人望而生畏。编写自定义组件的文档有点难以理解。我发现这个部分很有用:元件钩厂

因此,您需要从两个基本函数开始。一个函数创建元素,另一个函数更新元素。为了创造它,

代码语言:javascript
复制
// Assuming you've already defined L.TileLayer.WebGis somewhere
// and attached it to the global L

const createWebGisLayer = (props, context) => {

  const instance = L.tileLayer.webGis(props.url, {...props})

  return { instance, context }

}

然后,您需要另一个函数来处理您想要滴入组件中的任何更新。例如,如果组件的某个支柱发生了变化,您需要显式地告诉react传单来更新该组件的基础传单实例:

代码语言:javascript
复制
const updateWebGisLayer = (instance, props, prevProps) => {

  if (prevProps.url !== props.url) {
    if (instance.setUrl) instance.setUrl(props.url)
  }

  if (prevProps.userId !== props.userId) {
    if (instance.setUserId) instance.setUserId(props.userId)
  }

}

您需要这些设置函数来告诉react传单,如果urluserId (或任何其他)支持在react中发生变化,它需要重新修改传单层。setUrl已经存在于L.TileLayer上,但是您需要定义一个更新L.TileLayer.WebGis实例的userId选项的setUserId。如果不包括这些内容,则当组件的道具发生更改时,组件将不会更新。

要将所有这些放在一起,您可以使用createLayerComponent工厂函数:

代码语言:javascript
复制
const WebGisLayer = createLayerComponent(createWebGisLayer, updateWebGisLayer)
export WebGisLayer

WebGisLayer现在是一个反应组件,您可以使用它作为MapContainer的子组件。

代码语言:javascript
复制
const App = () => {

  const [userId, setUserId] = useState('user123')

  return (
    <MapContainer center={center} zoom={zoom}>
      <WebGisLayer 
        url="some_url" 
        userId={userId}
        otherPropsYouNeed={otherProps} />
    </MapContainer>
  )

}

当组件加载时,它将运行传单代码并将传单组件添加到映射中。如果userId由于某些setstate调用而发生变化,则updateWebGisLayer函数会告诉react传单更新基础传单组件。

有很多方法可以做到这一点,但我认为这是最直接的方法。我还没有机会对这段代码进行测试,因此您将不可避免地需要使用它才能正常工作,但这应该会让您开始工作。

票数 3
EN

Stack Overflow用户

发布于 2021-05-27 08:55:02

对于任何使用react-leaflettypescript的人:我在基于塞斯·卢茨克的回答的LeafletJS样式和类型记录中重新创建了小册子中的小猫例子

Javascript:

代码语言:javascript
复制
import L from "leaflet";
import { createLayerComponent } from "@react-leaflet/core";

// @see https://stackoverflow.com/a/65713838/4295853
// @ts-ignore
L.TileLayer.Kitten = L.TileLayer.extend({
    getTileUrl: function(coords: L.Coords) {
        var i = Math.ceil( Math.random() * 4 );
        return "https://placekitten.com/256/256?image=" + i;
    },
    getAttribution: function() {
        return "<a href='https://placekitten.com/attribution.html'>PlaceKitten</a>"
    }
});

// @ts-ignore
L.tileLayer.kitten = function() {
    // @ts-ignore
    return new L.TileLayer.Kitten();
}

// @ts-ignore
const createKittenLayer = (props, context) => {
    // @ts-ignore
    const instance = L.tileLayer.kitten(props.url, {...props});
    return {instance, context};
}

// @ts-ignore
const updateKittenLayer = (instance, props, prevProps) => {
    if (prevProps.url !== props.url) {
        if (instance.setUrl) instance.setUrl(props.url)
    }

    if (prevProps.userId !== props.userId) {
        if (instance.setUserId) instance.setUserId(props.userId)
    }
}

const KittenLayer = createLayerComponent(createKittenLayer, updateKittenLayer);
export default KittenLayer;

打字本(实用而非传单惯例见所以请回答我的意见):

代码语言:javascript
复制
import L, { Coords, DoneCallback, GridLayer } from "leaflet";
import {createLayerComponent, LayerProps } from "@react-leaflet/core";
import { ReactNode } from "react";

interface KittenProps extends LayerProps {
    userId: string,
    children?: ReactNode // PropsWithChildren is not exported by @react-leaflet/core
}

class Kitten extends L.TileLayer {

    getTileUrl(coords: L.Coords) {
        var i = Math.ceil( Math.random() * 4 );
        return "https://placekitten.com/256/256?image=" + i;
    }

    getAttribution() {
        return "<a href='https://placekitten.com/attribution.html'>PlaceKitten</a>"
    }

}

const createKittenLayer = (props: KittenProps, context:any) => {
    const instance = new Kitten("placeholder", {...props});
    return {instance, context};
}

const updateKittenLayer = (instance: any, props: KittenProps, prevProps: KittenProps) => {
      if (prevProps.userId !== props.userId) {
        if (instance.setUserId) instance.setUserId(props.userId)
      }
    
}

const KittenLayer = createLayerComponent(createKittenLayer, updateKittenLayer);
export default KittenLayer;
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65663826

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档