简体   繁体   English

ag-grid 使用钩子做出反应会导致在某些环境中重新安装组件

[英]ag-grid react using hooks causes remount of the component on some environments

Long story short: on some environments using react useState hook causes ag grid to refresh itself.长话短说:在某些环境中,使用 react useState 钩子会导致 ag 网格自行刷新。 It's behaves like component was mounted again from scratch, so you'd lost scroll position etc. I am using infinte scroll mode, but same behaviour is present regardless of scroll type.它的行为就像组件是从头开始重新安装的,所以你会丢失滚动 position 等。我使用的是无限滚动模式,但无论滚动类型如何,都存在相同的行为。 In example below i am trying to use useState hook in order to update custom div in onViewportChanged callback:在下面的示例中,我尝试使用 useState 挂钩来更新 onViewportChanged 回调中的自定义 div:

function Grid({ columnDefinition, config }) {
const domInfoRef = useRef(null);

const [actualRange, setActualRange] = useState({ from: null, to: null, total: null });

  function onViewportChanged(data) {
     if (config.paginationStyle === 'scroll' && domInfoRef.current) {
        const renderedNodes = data.api.getRenderedNodes();
        const firstIndex = renderedNodes[0].rowIndex;
        const lastIndex = renderedNodes[renderedNodes.length - 1].rowIndex;
        /*
        React "useState" inside AG grid callbacks causes unstable behaviour and refresh of component
        on some environments.
        This not works: 
        setActualRange({from: firstIndex + 1, to: ${lastIndex + 1}, total: data.api.getDisplayedRowCount()})
        In order to update status there is necessary to do this using plain js as below.
        */
        // update page-info after scrolling in "scroll" pagination style
        domInfoRef.current.textContent = `${firstIndex + 1} - ${lastIndex + 1} of ${data.api.getDisplayedRowCount()}`;
      }
   }
return (
<Fragment>
    <div className={`page-info`}>
        <span ref={domInfoRef}>
            {actualRange.from} - {actualRange.to} of {actualRange.total}
        </span>
    </div>
    <AgGridReact
        pagination={false}
        paginationPageSize={config.itemsPerPage}
        cacheBlockSize={config.itemsPerPage}
        maxBlocksInCache={config.itemsPerPage}
        rowModelType={'serverSide'}
        rowData={gridData}
        onGridReady={onGridReady}
        serverSideDatasource={createDataSource()}
        serverSideStoreType={'partial'}
        rowSelection='single'
        onViewportChanged={onViewportChanged}
        blockLoadDebounceMillis={100}
    >
        {columnDefinition.map((column) => {
            return (
                <AgGridColumn
                    headerName={column.headerName}
                    field={column.field}
                    suppressMenu={true}
                    sortable={column.sortable}
                    key={column.field}
                    resizable={column.resizable}
                    onCellClicked={column.onCellClicked}
                    cellRenderer={renderers[column.field] ? column.field : null}
                    valueFormatter={column.valueFormatter ?? null}
                    suppressSizeToFit={column.suppressSizeToFit}
                ></AgGridColumn>
            );
        })}
    </AgGridReact>
</Fragment>;
}
);

Same story if I will use react inside cell renderers function (of course after registering that render in ag grid inside frameworkComponents).如果我将在单元格渲染器 function 中使用反应,则同样的故事(当然是在框架组件内的 ag 网格中注册该渲染之后)。 Rendering alone and all other functions from grid like sorting etc works fine.单独渲染和网格中的所有其他功能(如排序等)都可以正常工作。 But I have no really clue what thing may cause this issue.但我真的不知道是什么原因导致了这个问题。 AG grid version is 25.2.0, React version is 16.14.0. AG 网格版本是 25.2.0,React 版本是 16.14.0。 Thank you in advance for any clue.提前感谢您提供任何线索。 I've tried to use memo without any success.我尝试使用备忘录但没有成功。 And the strangest thing is that is works on some environments fine and it is not depend on browser or OS.最奇怪的是,它可以在某些环境下正常工作,并且不依赖于浏览器或操作系统。

Workaround: Wrap AGGrid inside useState hook:解决方法:将 AGGrid 包裹在 useState 挂钩中:

    const [grid, setGrid] = useState(null);


    const agGrid = () =>{
    return(
     <AgGridReact
            pagination={false}
            paginationPageSize={config.itemsPerPage}
            cacheBlockSize={config.itemsPerPage}
            maxBlocksInCache={config.itemsPerPage}
            rowModelType={'serverSide'}
            rowData={gridData}
            onGridReady={onGridReady}
            serverSideDatasource={createDataSource()}
            serverSideStoreType={'partial'}
            rowSelection='single'
            onViewportChanged={onViewportChanged}
            blockLoadDebounceMillis={100}
        >
            {columnDefinition.map((column) => {
                return (
                    <AgGridColumn
                        headerName={column.headerName}
                        field={column.field}
                        suppressMenu={true}
                        sortable={column.sortable}
                        key={column.field}
                        resizable={column.resizable}
                        onCellClicked={column.onCellClicked}
                        cellRenderer={renderers[column.field] ? column.field : null}
                        valueFormatter={column.valueFormatter ?? null}
                        suppressSizeToFit={column.suppressSizeToFit}
                    ></AgGridColumn>
                );
            })}
        </AgGridReact>
    )
    }  
useEffect(() => {
    setGrid(<agGrid/>);
  }, []);

return (
<Fragment>
    <div className={`page-info`}>
        <span ref={domInfoRef}>
            {actualRange.from} - {actualRange.to} of {actualRange.total}
        </span>
    </div>
   {grid}
</Fragment>;
}
)

Explanation: This workaround forces to use single (same) instance of AG-grid per component lifecycle.说明:此解决方法强制每个组件生命周期使用单个(相同)AG-grid 实例。 It should be considered as hack IMO.它应该被视为 hack IMO。 But it's working.但它正在工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM