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.12k stars 1.28k forks source link

[question] Best/Most Efficient/Easiest way to save ALL data grid state and Restore ALL data grid state #8799

Open minchaej opened 1 year ago

minchaej commented 1 year ago

Order ID or Support key 💳 (optional)

I am a premium user but shouldn't this be a secret?

Duplicates

Latest version

The problem in depth 🔍

Hi,

So my question is simple, I want to know the Best/Most Efficient/Easiest way to save ALL data grid state and Restore ALL data grid state.

My plan/approach:

  1. save ALL data grid state on localStorage
  2. retrieve ALL data grid state from localStorage and set the initial state
  3. So the user can continue with the datagrid that has the EXACT same state as seen before. (I really mean ALL states like density, column width, pagination, sort filter, open/close state of parent child row , visibility etc..)

Attaching some code just to make sure:

// save state like this
setInitialStateFromLocalStorage("author_state", apiRef.current.exportState())
// or 
const handleStateChange = React.useCallback((state: GridState) => {
    setInitialStateFromLocalStorage("author_state", state)
}

// retrieve state like this
apiRef.current.restoreState(state)
// or
initialState={getInitialStateFromLocalStorage("author_state")}

So I've spent time researching how this can be implemented, but came across several questions.

Questions:

  1. What is the difference between state retrieved by apiRef.current.exportState() and onStateChange? I get that the states returned by those two methods are different. apiRef.current.exportState() returns a state of type GridInitialStatePremium but onStateChange returns a state of type GridState. I also realized that those two types aren't compatible with each other and they store different properties and values (for example, GridState contains row density information, but GridInitialStatePremium doesn't contain any density information.).
  2. In addition to above, why are there two different state types that have different information? And which one should I use? Which one stores the comprehensive state?
  3. In the docs, it's mentioned that I can use apiRef.current.restoreState(state) or initialState to set state of the datagrid. However, after few trials, I've realized that those two methods behave differently. For example, initialState is able to properly set up row density, but apiRef.current.restoreState(state) does not, even though the input state was the same. Also, I figured out that setting state via apiRef.current.restoreState(state) invokes controlled model callbacks such as onFilterModelChange and onPaginationModelChange but initialState doesn't, so I didn't use initialState. What are the differences between those two methods and what should I use? So for example, the problem occurs when I want BOTH restoring row density state and invoking controlled model callbacks because they can only fulfill one requirement not both.
  4. Ultimate question: Since there are multiple approaches to my problem, what is the approach recommended by MUI team to store/save ALL states and restore ALL states on Data grid. I would love to know a clean method for this problem. I've tried restoring all state manually by calling all setter methods (like columnVisibilityModel, density), but the code is just too long and complex. I would like a one liner solution. I mean apiRef.current.exportState() or initialState should be the one liner solution in theory but it's apparently not.

Thank you so much for reading my long question. I really tried to provide as much info as possible to avoid confusion.

PS: I use DataGridPremium component

Your environment 🌎

No response

m4theushw commented 1 year ago

What is the difference between state retrieved by apiRef.current.exportState() and onStateChange?

onStateChange is not documented. We may expose it as stable but you shouldn't use it if possible. The state passed to it is the internal state, while apiRef.current.exportState provides a state that can be serialized and with less noise.

In addition to above, why are there two different state types that have different information? And which one should I use? Which one stores the comprehensive state?

If you use the initialState prop, apiRef.current.exportState or apiRef.current.restoreState they will all use the GridInitialStatePremium interface.

What are the differences between those two methods and what should I use?

The initialState prop is meant to be used only once, like when the grid is mounting for the first time. The value passed to it will be copied to the internal state. In the other side, apiRef.current.exportState can be used multiple times. You could use it if you need to restore multiple sessions. The controlled model callbacks are not called just because the way that the state management feature was implemented. Using initialState means that the value provided to the prop is copied to the internal state, while with the API method, there's an intermediary step that automatically calls the callbacks. It would make sense to also call the controlled callbacks when initialState is used.

Ultimate question: Since there are multiple approaches to my problem, what is the approach recommended by MUI team to store/save ALL states and restore ALL states on Data grid.

Both methods are recommended. apiRef.current.restoreState might be better if the state is fetched asynchronously, because initialState only works once.

minchaej commented 1 year ago

@m4theushw Thank you so much for your reply.

I see that your reply offers the definition of MUI methods and properties, but doesn't provide any solution to the dilemma/problem that I am facing. I hope I've clarified the problem I am currently facing.

My objective: what is the approach recommended by MUI team to LOCALLY store/save ALL states and LOCALLY restore ALL states on Data grid.

1. So I get that "apiRef.current.exportState provides a state that can be serialized and with less noise (compared to state from onStateChange." But the state returned from apiRef.current.exportState has crucial information omitted such as density information. The state returned from onStateChange has row density information, whereas the state returned from apiRef.current.exportState does not. So, using state from apiRef.current.exportState doesn't fulfill my objective. So what to do if I want to fulfill my objective? I need state data that is Comprehensive so that I can store the comprehensive state locally and retrieve the comprehensive state later. This is the dilemma.

2. Now, the next dilemma is that setting state via apiRef.current.restoreState(state) and initialState both has its pros and cons. But I need a method to set the state that can do what those two methods can do, and that was my question. This example will make this dilemma clearer.

"After few trials, I've realized that those two methods behave differently. For example, initialState is able to properly set up row density, but apiRef.current.restoreState(state) does not, even though the input state was the same."

"I figured out that setting state via apiRef.current.restoreState(state) invokes controlled model callbacks such as onFilterModelChange and onPaginationModelChange but initialState doesn't"

So the problem occurs when I want BOTH restoring row density state and invoking controlled model callbacks because they can only fulfill one requirement not both. I hope it's clear now. So what is the method that combines the functionality of those two methods, because I need the functionality of BOTH methods of apiRef.current.restoreState(state) and initialState?

  1. I am sorry but my question still hasn't been answered. Ultimate question: What is the approach recommended by MUI team to locally store/save ALL states and restore ALL states on Data grid. I would love to know a clean method for this problem. I've tried restoring all state manually by calling all setter methods (like columnVisibilityModel, density), but the code is just too long and complex. I would like a one liner solution. I mean apiRef.current.exportState() or initialState should be the one liner solution in theory but it's apparently not.

I hope my problem is clearer now and we could get a solution to this problem. Please let me know if you have any question.

Thank you so much for your time and consideration.