I need to use the MUI X Data Grid in a TypeScript web application that is not fully react based but sometimes only uses individual React components.
The following example code shows a prototype on how to create a functional API.
The idea is to use the GridApi to functionally interact with the grid component but the code seems pretty ugly and I'm wondering:
GridApi
?import * as React from 'react';
import ReactDOM from 'react-dom/client';
import {StyledEngineProvider} from '@mui/material/styles';
import {DataGrid, useGridApiRef} from '@mui/x-data-grid';
import type {GridApi} from '@mui/x-data-grid';
export type apiRefType = React.MutableRefObject<GridApi>;
type GridPropsType = {
hideFooter: boolean,
setApiRef: (ref: apiRefType) => void,
};
const Grid = ({setApiRef}: GridPropsType): JSX.Element => {
const apiRef = useGridApiRef();
setApiRef(apiRef);
return (
<React.StrictMode>
<StyledEngineProvider injectFirst>
<div style={{height: '100%', width: '100%'}}>
<DataGrid columns={[]} rows={[]}apiRef={apiRef} />
</div>
</StyledEngineProvider>
</React.StrictMode>
);
};
export const renderGrid = async (target: HTMLElement, hideFooter: boolean): Promise<apiRefType> => {
let apiRef: apiRefType | null = null;
const setApiRef = (ref: apiRefType): void => {
apiRef = ref;
};
return new Promise((resolve) => { // eslint-disable-line promise/avoid-new
ReactDOM.createRoot(target).render(<Grid hideFooter={hideFooter} setApiRef={setApiRef}/>);
setTimeout(() => {
if (apiRef === null) {
throw new Error('apiref was not initialized');
}
resolve(apiRef);
}, 0);
});
};
Olivier Tassinari offers an excellent solution in this SR
import { renderGrid } from "./demo";
const cols = [{ field: "username" }, { field: "age" }];
const rows = [{ id: 1, username: "@MUI", age: 20 }];
(async () => {
const target = document.getElementById("root");
const gridApi = await renderGrid(target, {
hideFooter: true
});
gridApi.current.updateColumns(cols);
gridApi.current.updateRows(rows);
})();
import * as React from "react";
import * as ReactDOM from "react-dom/client";
import { StyledEngineProvider } from "@mui/material/styles";
import { DataGrid, DataGridProps, useGridApiRef, GridApi } from "@mui/x-data-grid";
type Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>;
export type apiRefType = React.MutableRefObject<GridApi>;
type GridPropsType = {
options: Optional<DataGridProps, "rows" | "columns">;
setApiRef: (ref: apiRefType) => void;
};
const Grid = ({ setApiRef, options }: GridPropsType): JSX.Element => {
const apiRef = useGridApiRef();
React.useLayoutEffect(() => {
setApiRef(apiRef);
}, [setApiRef, apiRef]);
return (
<React.StrictMode>
<StyledEngineProvider injectFirst>
<div style={{ height: "100%", width: "100%" }}>
<DataGrid columns={[]} rows={[]} apiRef={apiRef} {...options} />
</div>
</StyledEngineProvider>
</React.StrictMode>
);
};
export const renderGrid = async (
target: HTMLElement,
options: GridPropsType["options"]
): Promise<apiRefType> => {
return new Promise((resolve) => {
// eslint-disable-line promise/avoid-new
ReactDOM.createRoot(target).render(
<Grid options={options} setApiRef={resolve} />
);
});
};