Removing the tileFactory from components props (to limit re-renderings).

This commit is contained in:
Eric van der Vlist 2022-10-29 21:16:50 +02:00
parent 4479b1bd99
commit 7f9400b395
4 changed files with 180 additions and 94 deletions

View File

@ -35,15 +35,6 @@ export const LayerStack: react.FC<LayerStackProperties> = (
) => {
const [coordinateSystem] = useAtom(coordinateSystemAtom);
const simpleTileFactory: TileFactory = useCallback(
(keyObject) => (
<Tile
href={`https://tile.openstreetmap.org/${keyObject.zoomLevel}/${keyObject.x}/${keyObject.y}.png`}
/>
),
[]
);
const numberOfTiledLayers =
props.numberOfTiledLayers === undefined ? 1 : props.numberOfTiledLayers;
@ -107,7 +98,6 @@ export const LayerStack: react.FC<LayerStackProperties> = (
key={key}
keyObject={keyObject}
viewPort={i === activeTiledLayer ? viewPort : undefined}
tileFactory={simpleTileFactory}
/>
</g>
);

View File

@ -2,10 +2,6 @@ import { render } from '@testing-library/react';
import TiledLayer from './TiledLayer';
import { TileFactory } from './types';
const fakeTileFactory: TileFactory = (keyObject) => (
<text>{JSON.stringify(keyObject)}</text>
);
describe('The TiledLayer component ', () => {
beforeEach(() => {
globalThis.cacheForTiledLayer = new Map();
@ -17,7 +13,6 @@ describe('The TiledLayer component ', () => {
<TiledLayer
keyObject={{ provider: 'osm', zoomLevel: 10, x: 5, y: 8 }}
viewPort={{ topLeft: { x: 1, y: 2 }, bottomRight: { x: 3, y: 2 } }}
tileFactory={fakeTileFactory}
/>
</svg>
);
@ -29,23 +24,35 @@ describe('The TiledLayer component ', () => {
<g
transform="translate(1, 2)"
>
<text>
{"provider":"osm","zoomLevel":10,"x":6,"y":10}
</text>
<g>
<image
height="1"
href="https://tile.openstreetmap.org/10/6/10.png"
width="1"
/>
</g>
</g>
<g
transform="translate(2, 2)"
>
<text>
{"provider":"osm","zoomLevel":10,"x":7,"y":10}
</text>
<g>
<image
height="1"
href="https://tile.openstreetmap.org/10/7/10.png"
width="1"
/>
</g>
</g>
<g
transform="translate(3, 2)"
>
<text>
{"provider":"osm","zoomLevel":10,"x":8,"y":10}
</text>
<g>
<image
height="1"
href="https://tile.openstreetmap.org/10/8/10.png"
width="1"
/>
</g>
</g>
</svg>
</div>
@ -59,7 +66,6 @@ describe('The TiledLayer component ', () => {
<TiledLayer
keyObject={{ provider: 'osm', zoomLevel: 10, x: 5, y: 8 }}
viewPort={{ topLeft: { x: 1, y: 2 }, bottomRight: { x: 3, y: 2 } }}
tileFactory={fakeTileFactory}
/>
</svg>
);
@ -68,7 +74,6 @@ describe('The TiledLayer component ', () => {
<TiledLayer
keyObject={{ provider: 'osm', zoomLevel: 10, x: 5, y: 8 }}
viewPort={{ topLeft: { x: 5, y: 0 }, bottomRight: { x: 5, y: 2 } }}
tileFactory={fakeTileFactory}
/>
</svg>
);
@ -80,44 +85,68 @@ describe('The TiledLayer component ', () => {
<g
transform="translate(1, 2)"
>
<text>
{"provider":"osm","zoomLevel":10,"x":6,"y":10}
</text>
<g>
<image
height="1"
href="https://tile.openstreetmap.org/10/6/10.png"
width="1"
/>
</g>
</g>
<g
transform="translate(2, 2)"
>
<text>
{"provider":"osm","zoomLevel":10,"x":7,"y":10}
</text>
<g>
<image
height="1"
href="https://tile.openstreetmap.org/10/7/10.png"
width="1"
/>
</g>
</g>
<g
transform="translate(3, 2)"
>
<text>
{"provider":"osm","zoomLevel":10,"x":8,"y":10}
</text>
<g>
<image
height="1"
href="https://tile.openstreetmap.org/10/8/10.png"
width="1"
/>
</g>
</g>
<g
transform="translate(5, 0)"
>
<text>
{"provider":"osm","zoomLevel":10,"x":10,"y":8}
</text>
<g>
<image
height="1"
href="https://tile.openstreetmap.org/10/10/8.png"
width="1"
/>
</g>
</g>
<g
transform="translate(5, 1)"
>
<text>
{"provider":"osm","zoomLevel":10,"x":10,"y":9}
</text>
<g>
<image
height="1"
href="https://tile.openstreetmap.org/10/10/9.png"
width="1"
/>
</g>
</g>
<g
transform="translate(5, 2)"
>
<text>
{"provider":"osm","zoomLevel":10,"x":10,"y":10}
</text>
<g>
<image
height="1"
href="https://tile.openstreetmap.org/10/10/10.png"
width="1"
/>
</g>
</g>
</svg>
</div>
@ -130,7 +159,6 @@ describe('The TiledLayer component ', () => {
<TiledLayer
keyObject={{ provider: 'osm', zoomLevel: 10, x: 5, y: 8 }}
viewPort={{ topLeft: { x: 1, y: 2 }, bottomRight: { x: 3, y: 2 } }}
tileFactory={fakeTileFactory}
/>
</svg>
);
@ -139,7 +167,6 @@ describe('The TiledLayer component ', () => {
<TiledLayer
keyObject={{ provider: 'osm', zoomLevel: 10, x: 4, y: 10 }}
viewPort={{ topLeft: { x: 5, y: 0 }, bottomRight: { x: 5, y: 2 } }}
tileFactory={fakeTileFactory}
/>
</svg>
);
@ -151,44 +178,68 @@ describe('The TiledLayer component ', () => {
<g
transform="translate(1, 2)"
>
<text>
{"provider":"osm","zoomLevel":10,"x":6,"y":10}
</text>
<g>
<image
height="1"
href="https://tile.openstreetmap.org/10/6/10.png"
width="1"
/>
</g>
</g>
<g
transform="translate(2, 2)"
>
<text>
{"provider":"osm","zoomLevel":10,"x":7,"y":10}
</text>
<g>
<image
height="1"
href="https://tile.openstreetmap.org/10/7/10.png"
width="1"
/>
</g>
</g>
<g
transform="translate(3, 2)"
>
<text>
{"provider":"osm","zoomLevel":10,"x":8,"y":10}
</text>
<g>
<image
height="1"
href="https://tile.openstreetmap.org/10/8/10.png"
width="1"
/>
</g>
</g>
<g
transform="translate(5, 0)"
>
<text>
{"provider":"osm","zoomLevel":10,"x":9,"y":10}
</text>
<g>
<image
height="1"
href="https://tile.openstreetmap.org/10/9/10.png"
width="1"
/>
</g>
</g>
<g
transform="translate(5, 1)"
>
<text>
{"provider":"osm","zoomLevel":10,"x":9,"y":11}
</text>
<g>
<image
height="1"
href="https://tile.openstreetmap.org/10/9/11.png"
width="1"
/>
</g>
</g>
<g
transform="translate(5, 2)"
>
<text>
{"provider":"osm","zoomLevel":10,"x":9,"y":12}
</text>
<g>
<image
height="1"
href="https://tile.openstreetmap.org/10/9/12.png"
width="1"
/>
</g>
</g>
</svg>
</div>
@ -201,7 +252,6 @@ describe('The TiledLayer component ', () => {
<TiledLayer
keyObject={{ provider: 'osm', zoomLevel: 10, x: 5, y: 8 }}
viewPort={{ topLeft: { x: -3, y: -1 }, bottomRight: { x: -2, y: 2 } }}
tileFactory={fakeTileFactory}
/>
</svg>
);
@ -213,58 +263,90 @@ describe('The TiledLayer component ', () => {
<g
transform="translate(-3, -1)"
>
<text>
{"provider":"osm","zoomLevel":10,"x":2,"y":7}
</text>
<g>
<image
height="1"
href="https://tile.openstreetmap.org/10/2/7.png"
width="1"
/>
</g>
</g>
<g
transform="translate(-2, -1)"
>
<text>
{"provider":"osm","zoomLevel":10,"x":3,"y":7}
</text>
<g>
<image
height="1"
href="https://tile.openstreetmap.org/10/3/7.png"
width="1"
/>
</g>
</g>
<g
transform="translate(-3, 0)"
>
<text>
{"provider":"osm","zoomLevel":10,"x":2,"y":8}
</text>
<g>
<image
height="1"
href="https://tile.openstreetmap.org/10/2/8.png"
width="1"
/>
</g>
</g>
<g
transform="translate(-2, 0)"
>
<text>
{"provider":"osm","zoomLevel":10,"x":3,"y":8}
</text>
<g>
<image
height="1"
href="https://tile.openstreetmap.org/10/3/8.png"
width="1"
/>
</g>
</g>
<g
transform="translate(-3, 1)"
>
<text>
{"provider":"osm","zoomLevel":10,"x":2,"y":9}
</text>
<g>
<image
height="1"
href="https://tile.openstreetmap.org/10/2/9.png"
width="1"
/>
</g>
</g>
<g
transform="translate(-2, 1)"
>
<text>
{"provider":"osm","zoomLevel":10,"x":3,"y":9}
</text>
<g>
<image
height="1"
href="https://tile.openstreetmap.org/10/3/9.png"
width="1"
/>
</g>
</g>
<g
transform="translate(-3, 2)"
>
<text>
{"provider":"osm","zoomLevel":10,"x":2,"y":10}
</text>
<g>
<image
height="1"
href="https://tile.openstreetmap.org/10/2/10.png"
width="1"
/>
</g>
</g>
<g
transform="translate(-2, 2)"
>
<text>
{"provider":"osm","zoomLevel":10,"x":3,"y":10}
</text>
<g>
<image
height="1"
href="https://tile.openstreetmap.org/10/3/10.png"
width="1"
/>
</g>
</g>
</svg>
</div>

View File

@ -3,6 +3,7 @@ import { range, isEqual } from 'lodash';
import { Rectangle, TileFactory, TileKeyObject } from './types';
import tileUri from './uris';
import tileFactory from './tile-factory';
/**
* @hidden
@ -26,8 +27,6 @@ export interface TiledLayerProperties {
keyObject: TileKeyObject;
/** The current viewport expressed in tiles coordinates */
viewPort?: Rectangle;
/** The factory to create tiles */
tileFactory: TileFactory;
}
/**
@ -49,9 +48,9 @@ export interface TiledLayerProperties {
* Idea stolen [on the web](https://dev.to/tiagof/react-re-mounting-vs-re-rendering-lnh)
*
* TODO: cache housekeeping
*
*
* TODO: test tiles'X and Y boundaries.
*
*
* TODO: remove tileFactory to facilitate memoisation.
*
*/
@ -84,7 +83,7 @@ export const TiledLayer: react.FC<TiledLayerProperties> = (
tiles.set(
key,
<g key={key} transform={`translate(${col}, ${row})`}>
{props.tileFactory(keyObject)}
{tileFactory(keyObject)}
</g>
);
}

View File

@ -0,0 +1,15 @@
import Tile from './Tile';
import { TileFactory, TileKeyObject } from './types';
/**
*
* @param keyObject The tile identifier
* @returns The `<Tile>` component
*/
export const tileFactory: TileFactory = (keyObject:TileKeyObject) => (
<Tile
href={`https://tile.openstreetmap.org/${keyObject.zoomLevel}/${keyObject.x}/${keyObject.y}.png`}
/>
);
export default tileFactory;