javascript - 使用 AutoSizer 包装 React-Beautiful-DND + React-Window 虚拟列表时遇到的设置问题

标签 javascript reactjs react-virtualized react-beautiful-dnd react-window

包装我的虚拟列表时 <FixedSizeList>组件(react-beautiful-dnd + react-window)带有 <AutoSizer>组件 (react-virtualized-auto-sizer) 我收到以下错误:

react-beautiful-dnd

A setup problem was encountered.

Invariant failed: provided.innerRef has not been provided with a HTMLElement.

如果我不包装 <FixedSizeList>,则不会发生该错误组件与 <AutoResizer>并提供硬编码值。

我的程序实现了 2 个独立的、不可拖动的列表,我可以在它们之间进行拖放操作。因为列表不可拖动,所以它不是典型的“板”,但我使用了 React-Beautiful-DND's CodeSandBox for React-Window Basic Board 作为使其工作的指南。

List.js :
import { Draggable, Droppable } from "react-beautiful-dnd";
import { FixedSizeList } from "react-window";
import AutoSizer from "react-virtualized-auto-sizer";
import ListItem from "./ListItem";
import React, { memo, useCallback } from "react";

const List = ({

        ID,
        data
    }) => {

    const listItemRenderer = useCallback(({ data, index, style }) => {

        const item = (data && data[index]);

        if (!item) {

            return null;
        }

        return (

            <Draggable
                key={item.ID}
                draggableId={item.ID}
                index={index}
            >
                {(provided) =>

                    <ListItem
                        data={item}
                        draggableProvided={provided}
                        virtualStyle={style}
                    />
                }
            </Draggable>
        );
    }, []);

    return (

        <Droppable
            droppableId={ID}
            mode={"virtual"}
            renderClone={(provided, snapshot, rubric) => (

                <ListItem
                    data={data[rubric.source.index]}
                    draggableProvided={provided}
                    isDragging={snapshot.isDragging}
                />
            )}
        >
            {(provided, snapshot) => {

                const dataLength = (data)
                    ? data.length
                    : 0;

                const itemCount = (snapshot.isUsingPlaceholder)
                    ? dataLength + 1
                    : dataLength;

                return (

                    <AutoSizer>  //Error here caused by wrapping <FixedSizeList> with <AutoSizer>
                        {({ width, height }) => (

                            <FixedSizeList
                                width={width}   //AutoSizer supplied value
                                height={height} //AutoSizer supplied value
                                itemSize={100}
                                itemCount={itemCount}
                                itemData={data}
                                outerRef={provided.innerRef}
                            >
                                {listItemRenderer}
                            </FixedSizeList>
                        )}
                    </AutoSizer>
                );
            }}
        </Droppable>
    );
};

export default memo(List);

ListItem.js :
import React, { memo } from "react";

const ListItem = ({

        data,
        draggableProvided,
        virtualStyle
    }) => {

    return (

        <div
            {...draggableProvided.draggableProps}
            {...draggableProvided.dragHandleProps}
            ref={draggableProvided.innerRef}
            style={{

                ...draggableProvided.draggableProps.style,
                ...virtualStyle
            }}

        >
            {data.name}
        </div>
    );
};

export default memo(ListItem);

不管错误如何,一切似乎仍然正常运行,但我真的很想在继续之前了解问题。

最佳答案

我挖了 AutoSizer 组件来寻找答案。
该错误已被记录,因为 childrenwidth 以来,AutoSizer HOC 的属性没有被渲染和 height值为 0 .这也是为什么一切仍然正常运行的原因,如 widthheight状态值最终被更新,但仅在初始渲染之后。
AutoSizer (index.esm.js):

// Avoid rendering children before the initial measurements have been collected.
// At best this would just be wasting cycles.
var bailoutOnChildren = false;

if (!disableHeight) {
if (height === 0) {
    bailoutOnChildren = true;
}
outerStyle.height = 0;
childParams.height = height;
}

if (!disableWidth) {
if (width === 0) {
    bailoutOnChildren = true;
}
outerStyle.width = 0;
childParams.width = width;
}

return createElement(
'div',
{
    className: className,
    ref: this._setRef,
    style: _extends({}, outerStyle, style) },
!bailoutOnChildren && children(childParams)
);
因此,解决方案是供应defaultWidthdefaultHeight props 具有非零值以确保组件在安装时呈现,尽管具有非自动大小:
//...

return (

    <AutoSizer
        defaultWidth={1}
        defaultHeight={1}
    >
        {({ width, height }) => (

            <FixedSizeList
                width={width} 
                height={height}e
                itemSize={100}
                itemCount={itemCount}
                itemData={data}
                outerRef={provided.innerRef}
            >
                {listItemRenderer}
            </FixedSizeList>
        )}
    </AutoSizer>
);

关于javascript - 使用 AutoSizer 包装 React-Beautiful-DND + React-Window 虚拟列表时遇到的设置问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62460388/

相关文章:

reactjs - React-virtualized,列表在滚动时闪烁/滞后

reactjs - 如何在虚拟化列表中使用选择下拉列表?

reactjs - 无限加载网格在错误的时间触发 loadMoreRows

javascript - 更改所有td颜色

javascript - JavaScript 正则表达式中的正面观察

asp.net - 使用 Jquery.post 时如何在 ASP.Net 中获取表单值

javascript - 'this' 在生命周期方法中如何工作?

javascript - 帮助进行 JSON 迭代

javascript - 如何在 React 中向其他组件传递值

javascript - React 博客网站的管理仪表板