如何在不完全基于React的TypeScript应用程序中使用MUI X DataGrid API。

huangapple go评论72阅读模式
英文:

How to use the MUI X DataGrid API in a TypeScript application that is not fully React based

问题

我需要在一个 TypeScript 网页应用中使用 MUI X DatGrid,该应用不是完全基于 React,有时只使用独立的 React 组件。

以下是如何创建一个功能性 API 的原型示例代码。

想法是使用 GridApi 与网格组件进行功能性交互,但代码看起来相当混乱,我在思考:

  • 是否有更聪明的方法来做这个?
  • 为什么需要在检索 GridApi 之前使用 setTimeout?
  • 是否有一种方法可以在不更改任何属性的情况下强制 DataGrid 刷新?
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);
  });
};

示例代码链接

英文:

I need to use the MUI X DatGrid 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:

  • is there a smarter way to do this?
  • why do i need the setTimeout before I can retrieve the GridApi?
  • is there a way to force the DataGrid to refresh without changing any properties?
import * as React from &#39;react&#39;;
import ReactDOM from &#39;react-dom/client&#39;;
import {StyledEngineProvider} from &#39;@mui/material/styles&#39;;
import {DataGrid, useGridApiRef} from &#39;@mui/x-data-grid&#39;;

import type {GridApi} from &#39;@mui/x-data-grid&#39;;
export type apiRefType = React.MutableRefObject&lt;GridApi&gt;;

type GridPropsType = {
  hideFooter: boolean,
  setApiRef: (ref: apiRefType) =&gt; void,
};


const Grid = ({setApiRef}: GridPropsType): JSX.Element =&gt; {
	const apiRef = useGridApiRef();

	setApiRef(apiRef);

	return (
		&lt;React.StrictMode&gt;
			&lt;StyledEngineProvider injectFirst&gt;
				&lt;div style={{height: &#39;100%&#39;, width: &#39;100%&#39;}}&gt;
					&lt;DataGrid columns={[]} rows={[]}apiRef={apiRef} /&gt;
				&lt;/div&gt;
			&lt;/StyledEngineProvider&gt;
		&lt;/React.StrictMode&gt;
	);
};

export const renderGrid = async (target: HTMLElement, hideFooter: boolean): Promise&lt;apiRefType&gt; =&gt; {
	let apiRef: apiRefType | null = null;
	const setApiRef = (ref: apiRefType): void =&gt; {
		apiRef = ref;
	};

	return new Promise((resolve) =&gt; { // eslint-disable-line promise/avoid-new
		ReactDOM.createRoot(target).render(&lt;Grid hideFooter={hideFooter} setApiRef={setApiRef}/&gt;);
		setTimeout(() =&gt; {
			if (apiRef === null) {
				throw new Error(&#39;apiref was not initialized&#39;);
			}

			resolve(apiRef);
		}, 0);
	});
};

答案1

得分: -1

Olivier Tassinari在这个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} />
    );
  });
};
英文:

Olivier Tassinari offers an excellent solution in this SR

import { renderGrid } from &quot;./demo&quot;;

const cols = [{ field: &quot;username&quot; }, { field: &quot;age&quot; }];
const rows = [{ id: 1, username: &quot;@MUI&quot;, age: 20 }];

(async () =&gt; {
  const target = document.getElementById(&quot;root&quot;);
  const gridApi = await renderGrid(target, {
    hideFooter: true
  });
  gridApi.current.updateColumns(cols);
  gridApi.current.updateRows(rows);
})();
import * as React from &quot;react&quot;;
import * as ReactDOM from &quot;react-dom/client&quot;;
import { StyledEngineProvider } from &quot;@mui/material/styles&quot;;
import { DataGrid, DataGridProps, useGridApiRef, GridApi } from &quot;@mui/x-data-grid&quot;;

type Optional&lt;T, K extends keyof T&gt; = Pick&lt;Partial&lt;T&gt;, K&gt; &amp; Omit&lt;T, K&gt;;

export type apiRefType = React.MutableRefObject&lt;GridApi&gt;;

type GridPropsType = {
  options: Optional&lt;DataGridProps, &quot;rows&quot; | &quot;columns&quot;&gt;;
  setApiRef: (ref: apiRefType) =&gt; void;
};

const Grid = ({ setApiRef, options }: GridPropsType): JSX.Element =&gt; {
  const apiRef = useGridApiRef();

  React.useLayoutEffect(() =&gt; {
    setApiRef(apiRef);
  }, [setApiRef, apiRef]);

  return (
    &lt;React.StrictMode&gt;
      &lt;StyledEngineProvider injectFirst&gt;
        &lt;div style={{ height: &quot;100%&quot;, width: &quot;100%&quot; }}&gt;
          &lt;DataGrid columns={[]} rows={[]} apiRef={apiRef} {...options} /&gt;
        &lt;/div&gt;
      &lt;/StyledEngineProvider&gt;
    &lt;/React.StrictMode&gt;
  );
};

export const renderGrid = async (
  target: HTMLElement,
  options: GridPropsType[&quot;options&quot;]
): Promise&lt;apiRefType&gt; =&gt; {
  return new Promise((resolve) =&gt; {
    // eslint-disable-line promise/avoid-new
    ReactDOM.createRoot(target).render(
      &lt;Grid options={options} setApiRef={resolve} /&gt;
    );
  });
};

huangapple
  • 本文由 发表于 2023年6月16日 16:03:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/76488139.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定