警告:React无法识别DOM元素上的`viewState`属性

4
我操纵组件的状态,并使用状态中的对象(输入参数)来显示一些信息。

const renderTooltip = ({ object: hoveredObject, x: pointerX, y: pointerY }) => {
  // console.log(hoveredObject);
  const {points} = hoveredObject;

  const calLoadTime = () => {
    const rawTime = points.reduce(
      (accumulator, currentValue) => 
      currentValue ? accumulator + currentValue.SPACES : accumulator, 
      0
    ) / points.length;

    return rawTime.toFixed(1);
  }

  return (
    <span
      style={{
        lineHeight: '20px',
        borderRadius: '3px',
        width: '200px',
        left: pointerX+10,
        top: pointerY+5,
      }}
    >
      {`Length: ${points.length}\n`}
    </span>
  )
}

但是收到了以下警告,我检查了一下,没有在DOM元素上操作state或有名为viewState的属性?这个警告是什么意思?

警告:React不认识DOM元素上的viewState属性。如果你想要它作为自定义属性出现在DOM中,请将它拼写为小写的viewstate。如果你是从父组件中意外传递它的,请将它从DOM元素中删除。

下面是我的组件的完整代码:

import React, { memo, useEffect, useRef, useState } from 'react';
import DeckGL, {HexagonLayer} from 'deck.gl';
import { StaticMap } from 'react-map-gl';

import { INITIAL_VIEW_STATE, LAYER_CONFIGS } from './configs';
import { addMapControl } from './tools';
import { MAPBOX_TOKEN } from './constants';
import styles from './index.less';

const Map = (props) => {
  const {
    controller = true,
    baseMap = true,
    initialViewState = INITIAL_VIEW_STATE,
    layerType = '3d-heatmap',
    renderTooltip = DEFAULT_RENDER_TOOLTIP,
  } = props;

  const [tooltip, setTooltip] = useState({
    object: null,
    // eslint-disable-next-line react/no-unused-state
    x: 0,
    // eslint-disable-next-line react/no-unused-state
    y: 0,
  })

  /**
   * layers render function
   */
  const renderLayers = () => {
    const {
      data,
      accData = [],
      accSpeed = 0.1,
      accRadiusScale = 4,
      accRadiusMaxPixels = 200,
      accColorRange,
      coverage = 1,
      radius,
      elevationScale,
      ...otherProps
    } = props;
    const layers = [];

    layers.push(
      new HexagonLayer({
        ...LAYER_CONFIGS.AugmentHexagonLayer,
        ...otherProps,
        coverage,
        data,
        radius,
        onHover: setTooltip,
      }),
    );

    return layers;
  }

  /**
   * add Control for language switching
   * @param {*} event 
   */
  const addControlHandler = (event) => {
    const map = event && event.target;
    if (map) {
      addMapControl(map);
    }
  };

  const { object } = tooltip || {};

  return (
    <DeckGL
      width="100%"
      height="100%"
      layers={renderLayers()} // eslint-disable-line
      initialViewState={initialViewState}
      controller={controller}
    >
      {baseMap && (
        <StaticMap
          onLoad={addControlHandler}
          reuseMaps
          mapStyle="mapbox://styles/mapbox/dark-v9"
          preventStyleDiffing
          mapboxApiAccessToken={MAPBOX_TOKEN}
        />
      )}
      {object && renderTooltip(tooltip)}
    </DeckGL>
  );
}

我使用了一些第三方包来在地图上显示工具提示。

renderTooltip属性是由我上面提到的输入renderTooltip函数赋值的,我使用tooltip状态来控制是否应该在页面中显示工具提示。

注:根据deck.gl文档,onHover将在以下情况下触发:

onHover(函数,可选)

当鼠标进入/离开此deck.gl图层的对象时,将调用此回调,并带有以下参数:

  • info

  • event-源事件

根据错误跟踪路径,在我的<span>元素中抛出错误,这就是我最初认为是renderTooltip问题的原因。

Warning: React does not recognize the `viewState` prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase `viewstate` instead. If you accidentally passed it from a parent component, remove it from the DOM element.
    in span (created by Map)
    in div (created by DeckGL)
    in div (created by DeckGL)
    in DeckGL (created by Map)
    in Map (created by SpatialTemporal)
    in section (created by SpatialTemporal)
    in SpatioMap
    in section
    in Unknown (created by LBS)
    in div
    in div
    in Unknown (created by LBS)
    in LBS (created by Connect(LBS))
    in Connect(LBS) (created by DynamicComponent)
    in DynamicComponent (created by Route)
    in Route (created by BasicLayout)
    in Switch (created by BasicLayout)
    in div (created by BasicLayout)
    in div (created by Basic)
    in Basic (created by Adapter)
    in Adapter (created by BasicLayout)
    in div (created by BasicLayout)
    in BasicLayout (created by Adapter)
    in Adapter (created by BasicLayout)
    in div (created by BasicLayout)
    in BasicLayout (created by Adapter)
    in Adapter (created by BasicLayout)
    in div (created by ContainerQuery)
    in ContainerQuery (created by BasicLayout)
    in DocumentTitle (created by SideEffect(DocumentTitle))
    in SideEffect(DocumentTitle) (created by BasicLayout)
    in BasicLayout (created by Connect(BasicLayout))
    in Connect(BasicLayout) (created by DynamicComponent)
    in DynamicComponent (created by Route)
    in Route (created by DvaRoot)
    in Switch (created by DvaRoot)
    in Router (created by DvaRoot)
    in LocaleProvider (created by DvaRoot)
    in Provider (created by DvaRoot)
    in DvaRoot


请问您能否展示一下该组件的代码? - Hai Pham
我认为警告信息不是来自代码的这一部分。 - aquilesb
@HaiPham 谢谢提醒!我使用了一些第三方软件包来在地图中显示工具提示,并将其实现在描述底部,通过删除一些无用代码使其更清晰。 :-) - hijiangtao
@aquilesb 和上面的内容一样。非常感谢。 :-) - hijiangtao
3个回答

3
今天我遇到了同样的问题,通过将提示工具不直接添加到deckGL中而解决了该问题:

return (
  <React.Fragment>
    <DeckGL
      width="100%"
      height="100%"
      layers={renderLayers()} // eslint-disable-line
      initialViewState={initialViewState}
      controller={controller}
    >
      {baseMap && (
        <StaticMap
          onLoad={addControlHandler}
          reuseMaps
          mapStyle="mapbox://styles/mapbox/dark-v9"
          preventStyleDiffing
          mapboxApiAccessToken={MAPBOX_TOKEN}
        />
      )}
    </DeckGL>
    {object && renderTooltip(tooltip)}
 </React.Fragment>
  );


我尝试了这种方式,并在使用 onHover 回调函数设置状态时收到了警告。你以前遇到过同样的情况吗? - hijiangtao

0

所以,我也遇到了同样的问题。这是一个微妙的问题,似乎你不应该将渲染好的工具提示作为DeckGL的子元素传递,而是应该作为一个函数,在调用时进行渲染。所以,在你的情况下,你可以这样做:

  return (
    <DeckGL
      ...
    >
      ...
      {object && renderTooltip.bind(this, tooltip)}
    </DeckGL>
  );

bind 的调用允许您将要传递的参数进行柯里化,而不实际调用底层函数。由 DeckGL 传递的任何 props 都将作为 tooltip 后面的下一个参数传递。

还有其他解决方法,但关键是传递一个将呈现而不是已呈现组件的函数。


0

看起来这个警告是来自于deck.gl,尝试修改Map组件:

const Map = (props) => {
  const {
    controller = true,
    baseMap = true,
    initialViewState = INITIAL_VIEW_STATE,
    layerType = '3d-heatmap',
    renderTooltip = DEFAULT_RENDER_TOOLTIP,
    ...rest //rest props
  } = props;
//...

谢谢!我有一个问题,我应该在哪里使用rest对象,否则为什么要将无用的属性重置到另一个对象中?这是否属于deck.gl的内部问题? - hijiangtao
我尝试重置其他未使用的属性,但当我移动鼠标显示工具提示时仍然会出现错误,但并不总是,在刷新页面时有时会出现。 - hijiangtao
我在这里看到逻辑错误:{object && renderTooltip(tooltip)}。如果你的 if (object) 是真的,即使它是 {},请尝试修复它并刷新。 - Hai Pham
我确实注意到这个逻辑,但是我认为它永远不会被赋值为{},因为我在开始时使用useState进行了初始化,尽管在渲染部分中使用了const { object } = tooltip || {}; - hijiangtao
@hijiangtao,这有点复杂,我不熟悉deck.gl,所以你能否创建一个https://codesandbox.io/项目以便于跟踪? - Hai Pham

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接