【问题标题】:React performance issue with drag and drop通过拖放反应性能问题
【发布时间】:2021-08-13 13:54:29
【问题描述】:

在向框中添加元素时,我正在努力解决反应性能问题。为此,我使用 React Rnd 库。

我有一个地图,当数组中有新项目时呈现项目:

children.map((children, index) => (
        <Box
          key={children.id}
          isPreview={false}
          index={index}
          slot={name}
          {...children}
        />
      )),

Box 组件是库中的Rnd 组件,它实际上是一个很大的组件。

<Rnd
      style={{
       //2 lines off css
      }}
      minHeight={MIN_SIZE}
      minWidth={MIN_SIZE}
      enableResizing={isResizingEnabled}
      disableDragging={condition}
      size={size}
      position={Position}
      lockAspectRatio={isAspectRatioLocked}
      onResizeStart={onResizeStart}
      onDragStop={(e, newPosition) => {
        onDragStop(newPosition)
      }}
      onResizeStop={(e, dir, ref, delta, newPosition) =>
        onResizeStop(ref, newPosition)
      }
      resizeHandleComponent={createResizeHandles(isInCollision)}
      dragGrid={grid}
      resizeGrid={grid}
      bounds="parent"
    >
      <StyledDiv
        onClick={() => {
          
          dispatch(actions.setEditMode({...properties}))
        }}
        isBeingCropped={isCroppingEnabled}
        isPreview={isPreview}
        isEditable={isEditable}
        isInCollision={isInCollision}
        isEditStartable={isEditStartable}
      >
        {children}
      </StyledDiv>
    </Rnd>

问题是当我向这个盒子添加 4 个元素时,有时需要 2-4 秒... 知道如何解决吗?

是否有任何简单的解决方案可以使其更快,或者我是否必须研究每个函数/挂钩并使用一些 useCallback、useMemo 或其他东西对其进行优化?

【问题讨论】:

    标签: javascript reactjs drag-and-drop


    【解决方案1】:

    是的,您应该从避免不必要的重新渲染开始,然后您可以考虑优化每个功能。由于这是一个拖放组件,我相信大多数道具会在您拖动元素时经常更改,因此在实际重新渲染组件之前确保每次重新渲染都很重要。

    这里有几个地方可以开始。

    只将需要的东西传递给盒子

    不要将孩子分散到 Box 中,而是只传递需要的内容,这将避免任何不必要的重新渲染,以防万一那里有 Box 不关心的道具。

    children.map((children, index) => (
            <Box
              key={children.id}
              isPreview={false}
              index={index}
              slot={name}
            />
          )),
    

    使用记忆避免重新渲染

    当对象没有移动时,您可能希望避免任何重新渲染,因此要记住组件。

    对函数使用 useCallback

    这将防止每次重新渲染父级时分配回调。我看到的最大罪魁祸首是 onClick 处理程序,它依赖于动作,因此当动作发生变化时会一次又一次地渲染盒子,即使盒子不依赖于所有动作

    const { setEditMode } = dispatch;
    
    const handleDragStop = useCallback(
      (e, newPosition) => {
        onDragStop(newPosition);
      },
      [onDragStop]
    );
    
    const handleResizeStop = useCallback(
      (e, dir, ref, delta, newPosition) => {
        onResizeStop(ref, newPosition);
      },
      [onResizeStop]
    );
    const handleOnClick = useCallback(() => {
      dispatch(setEditMode({ ...properties }));
    }, [onResizeStop, setEditMode, properties]);
    
    <Rnd
      style={
        {
          //2 lines off css
        }
      }
      minHeight={MIN_SIZE}
      minWidth={MIN_SIZE}
      enableResizing={isResizingEnabled}
      disableDragging={condition}
      size={size}
      position={Position}
      lockAspectRatio={isAspectRatioLocked}
      onResizeStart={onResizeStart}
      onDragStop={handleDragStop}
      onResizeStop={handleResizeStop}
      resizeHandleComponent={createResizeHandles(isInCollision)}
      dragGrid={grid}
      resizeGrid={grid}
      bounds="parent"
    >
      <StyledDiv
        onClick={handleClick}
        isBeingCropped={isCroppingEnabled}
        isPreview={isPreview}
        isEditable={isEditable}
        isInCollision={isInCollision}
        isEditStartable={isEditStartable}
      >
        {children}
      </StyledDiv>
    </Rnd>;
    

    如果您需要任何进一步的解释,请查看我写的这篇文章here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-17
      • 1970-01-01
      • 1970-01-01
      • 2018-03-09
      相关资源
      最近更新 更多