From a7f78e0fa994730f5844e6063615285f1084438c Mon Sep 17 00:00:00 2001 From: evlist Date: Tue, 18 Oct 2022 16:52:24 +0200 Subject: [PATCH] Avoid uncessessary rerendering (see https://medium.com/swlh/making-stupid-react-smart-in-re-rendering-5f04b5bab327 ). --- src/components/map/Map.tsx | 13 +++--- src/components/map/TiledLayer.tsx | 73 ++++++++++++++++--------------- 2 files changed, 45 insertions(+), 41 deletions(-) diff --git a/src/components/map/Map.tsx b/src/components/map/Map.tsx index 6e5447d..b97ce21 100644 --- a/src/components/map/Map.tsx +++ b/src/components/map/Map.tsx @@ -1,4 +1,4 @@ -import react, { useState } from 'react'; +import react, { useCallback, useState } from 'react'; import Handlers from './Handlers'; import Tile from './Tile'; import TiledLayer from './TiledLayer'; @@ -16,10 +16,13 @@ export const Map: react.FC = (props: MapProperties) => { shift: { x: 0, y: 0 }, }); - const simpleTileFactory: TileFactory = (keyObject) => ( - + const simpleTileFactory: TileFactory = useCallback( + (keyObject) => ( + + ), + [] ); const transformMap = ( diff --git a/src/components/map/TiledLayer.tsx b/src/components/map/TiledLayer.tsx index e780c18..f7d5ad1 100644 --- a/src/components/map/TiledLayer.tsx +++ b/src/components/map/TiledLayer.tsx @@ -1,4 +1,4 @@ -import react, { useRef } from 'react'; +import react, { memo, useRef } from 'react'; import { range, isEqual } from 'lodash'; import { Rectangle, TileFactory, TileKeyObject } from './types'; @@ -23,45 +23,46 @@ export interface TiledLayerProperties { * * This component has no need to know the number nor the size of its tiles: tiles can be added when needed and * its unit is the tile size (the parent component needs to transform its enclosing SVG group to adapt its units) - * + * * TODO: test tiles'X and Y boundaries. * */ -export const TiledLayer: react.FC = ( - props: TiledLayerProperties -) => { - console.log(`Rendering TiledLayer: ${JSON.stringify(props)}`); - const tiles = useRef({}); - const previousKeyObject = useRef(props.keyObject); - if (!isEqual(props.keyObject, previousKeyObject.current)) { - previousKeyObject.current = props.keyObject; - tiles.current = {}; - } - - range(props.viewPort.topLeft.y, props.viewPort.bottomRight.y + 1).map( - (row) => { - range(props.viewPort.topLeft.x, props.viewPort.bottomRight.x + 1).map( - (col) => { - const keyObject = { - provider: props.keyObject.provider, - zoomLevel: props.keyObject.zoomLevel, - x: props.keyObject.x + col, - y: props.keyObject.y + row, - }; - const key = tileUri(keyObject); - if (!Object.hasOwn(tiles.current, key)) { - tiles.current[key] = ( - - {props.tileFactory(keyObject)} - - ); - } - } - ); +export const TiledLayer: react.FC = memo( + (props: TiledLayerProperties) => { + console.log(`Rendering TiledLayer: ${JSON.stringify(props)}`); + const tiles = useRef({}); + const previousKeyObject = useRef(props.keyObject); + if (!isEqual(props.keyObject, previousKeyObject.current)) { + previousKeyObject.current = props.keyObject; + tiles.current = {}; } - ); - return <>{Object.values(tiles.current)}; -}; + range(props.viewPort.topLeft.y, props.viewPort.bottomRight.y + 1).map( + (row) => { + range(props.viewPort.topLeft.x, props.viewPort.bottomRight.x + 1).map( + (col) => { + const keyObject = { + provider: props.keyObject.provider, + zoomLevel: props.keyObject.zoomLevel, + x: props.keyObject.x + col, + y: props.keyObject.y + row, + }; + const key = tileUri(keyObject); + if (!Object.hasOwn(tiles.current, key)) { + tiles.current[key] = ( + + {props.tileFactory(keyObject)} + + ); + } + } + ); + } + ); + + return <>{Object.values(tiles.current)}; + }, + isEqual +); export default TiledLayer;