Next.js 和 ag-grid - ResizeObserver.observe 尝试呈现客户端时出错

Next.js and ag-grid - ResizeObserver.observe error while trying to render client side

我有一个产品页面,它由一个搜索栏组件和一个包含 ag-grid 导入和设置的网格组件组成。

简化后的产品页面如下所示:


// Dynamic import for client side rendering
const ProductGrid = dynamic(() => import('../modules/products/gridComponent'), {
    ssr: false,
    loading: () => <p>...</p>
})
const Searchbar = dynamic(() => import('../modules/common/Searchbar'), {
    ssr: false,
    loading: () => <p>...</p>
})

const Products = () => {

    // State
    const containerStyle = useMemo(() => ({ width: '100%', height: '100%' }), []);
    const [searchQuery, setSearchQuery] = useState('');
    const [searchLimit, setSearchLimit] = useState(5);
    // Custom hook to fetch from API (has useEffect with searchQuery and searchLimit as dependencies)
    const [ rowData, gridRef, error ] = useDolibarrProducts(searchQuery, searchLimit);

    const updateProducts = useCallback((event) => {
        // Updates product list
        event.preventDefault();
        const query = event.target.elements.search.value;
        setSearchQuery(query);
        setSearchLimit(100);
    }, []);

    return (
        <Fragment>
            <Searchbar handleSubmit={(event) => updateProducts(event)} />
            <div style={containerStyle} className="ag-theme-alpine-dark">
                <ProductGrid gridRef={gridRef} rowData={rowData} />
            </div>
        </Fragment>
    );
}

export default Products;

网格组件如下所示:

import {AgGridReact} from "ag-grid-react";
import dynamic from "next/dynamic";

// I'm guessing using dynamic to import loadingComponent (a simple custom loading screen) serves no purpose here since gridComponent is already imported dynamically, but I've tried every scenario just in case
const loadingComponent = dynamic( () => import('./loadingComponent'), {
    ssr: false,
    loading: () => <p>...</p>
})

const GridComponent = (props) => {
    const defaultColDef = useMemo(() => {
        return {
            flex: 1,
            // make every column use 'text' filter by default
            filter: 'agTextColumnFilter',
            // enable floating filters by default
            floatingFilter: true,
            // make columns resizable
            resizable: true,
            // enable sorting
            sortable: true,
        };
    }, []);

    const [columnDefs] = useState([
        { field: "label" },
        { field: "ref", headerName: "Reference" },
        {
            field: "price",
            headerName: "Price (€)",
            filter: 'agNumberColumnFilter',
            filterParams: floatFilter,
            valueFormatter: priceFormatter,
        },
        {
            field: "stock",
            filter: 'agNumberColumnFilter',
            cellRenderer: stockRenderer
        },
        {
            field: "action",
            cellRenderer: actionRender,
            floatingFilter: false,
            sortable: false,
            filter: false,
        }
    ]);

    const loadingOverlayComponent = useMemo(() => {
        return loadingComponent;
    }, []);


    return (
        <Fragment>
            <AgGridReact
                ref={props.gridRef}
                rowData={props.rowData}
                columnDefs={columnDefs}
                defaultColDef={defaultColDef}
                loadingOverlayComponent={loadingOverlayComponent}
            />
        </Fragment>
    );
};

export default GridComponent;

问题:

在没有 next.js(客户端,没有动态导入)的情况下使用相同的结构时,页面和组件工作正常。

然而,当我尝试移动到 next.js 时,ag-grid-community 库导致 Unhandled Runtime Error - TypeError: ResizeObserver.observe: Argument 1 is not an object. 现在 ResizeObserver 似乎是一个浏览器功能,它可以解释为什么 ag-grid 不适用于服务器端渲染,所以这就是为什么我使用 dynamic 导入网格组件以便它可以在客户端上渲染边,但问题依然存在。我不确定我可能错过了什么,但我的组件似乎在没有 next.js 的情况下在客户端工作,但在使用 next.js

时却在客户端不工作

解决方案:原来问题不是 ag-grid 与 Next.js 冲突,而是 ag-grid 与 React 18 冲突。

原来 React 18 引入了新的渲染语法,我的问题源于 npx create-react-app 在我使用它构建快速项目进行测试时使用旧语法。

当使用旧语法时,React 会像 运行 React 17 一样工作,这就是为什么 ag-grid 和 React 18 之间的冲突在我不使用时没有显示的原因接下来。

根据 https://github.com/ag-grid/ag-grid/issues/5090 看来问题正在解决。