Material UI (MUI) の DataGrid
には autosizeOptions
というパラメータが用意されており、これによりカラムの幅を列ヘッダーや行データのサイズを基準にしたり、DataGrid
の表示幅に合わせて自動でフィット(拡張)させることができます。
DataGrid : Autosizing
<DataGrid
{...otherProps}
autosizeOptions={{
outliersFactor: DEFAULT_GRID_AUTOSIZE_OPTIONS.outliersFactor,
includeOutliers: true, // 行データの幅に合わせる
includeHeaders: false, // 列ヘッダーの幅に合わせる
expand: true, // 表示幅に合わせて自動拡張
}}
/>
しかし、上記のように DataGrid
に autosizeOptions
パラメータを設定してもその内容が反映されません。
自動サイズ調整ができない原因
autosizeOptions
によるカラム幅の計算は、実際に列ヘッダーや行データが読み込まれて DataGrid
がレンダリングされてからでないと正確な算出ができません。
このため、単純に autosizeOptions
パラメータをセットしただけでは、DataGrid
の非同期の実行によって初期化直後の空のデータグリッドで計算されてしまうために、コンポーネントのレンダリングタイミングとの整合性が取れず、期待通りにカラムが自動調整されない状態になってしまいます。
対処方法
autosizeOptions
による自動サイズ調整を反映させるには、ReactDOM.flushSync
というメソッドを利用して DOM を強制的に同期的に更新する方法もありますが、React の公式ドキュメントには、「flushSync の使用は一般的ではなく、アプリのパフォーマンスを低下させる可能性がある」とのことなので、setTimeout
を利用してデータグリッドのレンダリング完了まで待機してから useGridApiRef
によって生成された DataGrid
への参照に autosizeColumns
を渡すことで指定したオプションにて自動サイズ調整を行います。
// 自動サイズ調整オプション const autosizeOptions = { outliersFactor: DEFAULT_GRID_AUTOSIZE_OPTIONS.outliersFactor, includeOutliers: true, includeHeaders: true, expand: true, } const FlexGrid = () => { const apiRef = useGridApiRef(); const [ isLoading, setIsLoading ] = React.useState( true ); React.useEffect(() => { const applyAutosize = async () => { setIsLoading( true ); try { // データグリッドのレンダリングが完了するまで待機 await new Promise( ( resolve ) => { setTimeout( resolve, 1000 ); } ); setIsLoading( false ); // autosizeColumns を非同期で更新 await new Promise( ( resolve ) => { setTimeout( () => { if ( typeof apiRef?.current?.autosizeColumns === 'function' ) { apiRef.current.autosizeColumns( autosizeOptions ); } resolve(); }, 200); } ); } catch ( error ) { console.error( "Autosize Error:", error ); setIsLoading( false ); } }; applyAutosize(); }, [ apiRef, autosizeOptions ] ); return ( <Box sx={{ height: 400, width: 680, margin: '10px auto' }}> <DataGrid apiRef={apiRef} rows={rows} columns={columns} loading={isLoading} autosizeOptions={autosizeOptions} /> </Box> ); } ReactDOM.createRoot(document.querySelector("#root")).render(<FlexGrid />);
このコードによって、Promise
内で setTimeout
によって DataGrid
のレンダリングを待ち、apiRef.current.autosizeColumns
メソッドが実行可能な状態で autosizeOptions
を更新しています。
以下より実際の表示デモで自動サイズ調整がレンダリング後に正しく反映されるのを確認できます。
See the Pen MUI DataGrid Autosizing by digistate (@digistate) on CodePen.