Select to view content in your preferred language

[esri.renderers.UniqueValueRenderer] #getSymbol() Please use getSymbolAsync if valueExpression is used

43
0
yesterday
lingyanmao
New Member

The following content comes from a translator, please forgive any inaccuracies. Thank you very much. Title

SceneLayer throws "Please use getSymbolAsync if valueExpression is used" when swapping a UniqueValueRenderer with valueExpression at runtime

Environment

  • ArcGIS Maps SDK for JavaScript version: 4.32
  • Layer type: esri/layers/SceneLayer (Hosted Scene Layer, geometryType is mesh, I3S service)
  • View type: esri/views/SceneView
  • Renderer: esri/renderers/UniqueValueRenderer using valueExpression (Arcade) instead of field

Description

When a UniqueValueRenderer with valueExpression is passed to the renderer property inside the constructor of SceneLayer, the layer loads and renders correctly with no console errors.

However, once the layer has already finished loading and is being rendered in the view, if I swap the renderer at runtime (i.e. sceneLayer.renderer = newUniqueValueRenderer, where newUniqueValueRenderer also uses valueExpression), the console keeps throwing:

[esri.renderers.UniqueValueRenderer] #getSymbol() Please use getSymbolAsync if valueExpression is used

Steps to reproduce

  1. Create a SceneLayer (mesh geometryType, Hosted I3S service) with a plain simple renderer passed in the constructor.
  2. Add it to the map and wait for sceneLayer.when() to resolve, confirming the layer is loaded and rendered.
  3. Then run:
    sceneLayer.renderer = {
    type: "unique-value",
    valueExpression: "var floor = $feature.floor_no; if (floor >= 10) return 'high'; return 'low';",
    uniqueValueInfos: [
    { value: "high", symbol: highSymbol },
    { value: "low", symbol: lowSymbol }
    ]
    }
  4. Check the browser console — a large number of Please use getSymbolAsync if valueExpression is used errors appear.

Expected behavior

Whether a valueExpression-based renderer is passed at construction time or assigned at runtime after the layer is already loaded, it should consistently be resolved through the async getSymbolAsync() path internally. There should be no code path calling the synchronous getSymbol(), and no console errors.

Actual behavior

  • Renderer with valueExpression passed at construction time: no errors, renders correctly.
  • Renderer with valueExpression assigned at runtime after the layer has loaded: errors are thrown repeatedly. My suspicion is that when SceneLayerView re-symbolizes features that are already present in the GPU buffers, it takes an internal synchronous code path that calls renderer.getSymbol() instead of getSymbolAsync().

Visually, the rendering still appears correct in most cases, but the sheer volume of console errors makes this unacceptable for a production app.

Current workaround

Instead of hot-swapping the renderer property, we now remove the layer from the map (view.map.remove(layer)) and recreate a brand-new SceneLayer instance with the new valueExpression-based renderer passed in the constructor, then add it back to the map. This avoids the error, but it means re-fetching and re-decoding all tiles every time the renderer changes, which is not ideal for performance.

Ask

Could the team please confirm:

  1. Is this a known limitation/bug specific to SceneLayer (as opposed to FeatureLayer, where runtime renderer swaps with valueExpression may behave differently)?
  2. Is there an officially recommended way to swap a valueExpression-based UniqueValueRenderer at runtime on an already-loaded SceneLayer without having to recreate the layer?
  3. Is there a plan to fix this internal synchronous call path in a future release?
0 Kudos
0 Replies