mui / mui-x

MUI X: Build complex and data-rich applications using a growing list of advanced React components, like the Data Grid, Date and Time Pickers, Charts, and more!
https://mui.com/x/
4.02k stars 1.24k forks source link

[docs] Encourage declarative programming of the datagrid #10205

Open lauri865 opened 1 year ago

lauri865 commented 1 year ago

Duplicates

Related page

https://mui.com/x/react-data-grid/state/#restore-the-state-with-initialstate

Kind of issue

Other

Issue description

Wanted to share some learnings, which would benefit other Datagrid users. While following the docs and implementing some core features for our datagrid, such as custom views, persistence, resetting views, etc., we were drawn into using the GridApi quite heavily, with methods such as exportState, restoreState, getAllColumns, etc.

This turned our code base into a hot mess of race conditions pretty soon (as well as some performance issues with loading the grid). The problems all boiled down to managing initial view in a declarative way via props, and persistent views in an imperative way, which the GridApi design led us to do.

A better way is to skip all the imperative mess and do everything declaratively, but that's not properly supported by the interface given to developers. ExportState returns internal state representation of columns and getAllColumns (or gridColumnDefinitionsSelector) cannot immediately be re-applied as a prop for the datagrid either, because it can include aggregationWrappedColumn columns.

We figured it out for our use case with custom selectors, and prop overrides, which made everything much more elegant as well as performant. What I'm suggesting is both improvements in the docs on that front, and making sure core APIs encourage declarative manipulation of the datagrid to save days of headaches for other developers. E.g. as an aexample getAllColumns or gridColumnDefinitionsSelector or alternative functionality should predictably return something that you can just re-pass as columns prop to the datagrid, rather than having to call GridApi to control internal state.

Context 🔦

Just as an example, for resetting the datagrid state, this issue (#4301 ) was also drawn into an imperative manipulation of the internal state, which becomes quite verbose to cover all cases (pinned columns, grouping, density, etc. – everything needs to be manually re-set to initial state). In a declarative paradigm where everything happens through the same root props, the solution could be to just re-set the sate that holds data for rootProp overrides (e.g. columns) and supply a new random key prop to the Datagrid to force re-setting all the internal state. 2 lines of code instead of 100+ in our case, and much less buggy, with 100% consistency.

Many related issues that suffer from trying to achieve these kinds of functionality imperatively through GridApi methods and side-effects to manipulate the state (and suffering many of the issues we did with either race conditions, states not being updated, etc. that all got solved for us with dropping the suggested imperative approach):

8799

5704

5418

5461

5675

5127

4779

4620

...and more

(sorry for the long post, but I've spent weeks working on this, and this epiphany has made it so much pleasurable to work with the datagrid for me personally, that I want to save everyone else the same pain)

puddleglum56 commented 4 months ago

Hi @lauri865 I'm currently dealing with a similar headache: trying to persist grid state to Indexed DB. Would you mind sharing more about your solution?