-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[DataGrid] Refactor state #412
Conversation
655ceba
to
ad12572
Compare
da62f82
to
d847d5f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are getting closer. I think that we should address the following before moving forward (so we keep master in a state that can be released at any time). Maybe @DanailH could help? :)
- 🚀 The documentation is unusable. There is a major performance regression on https://deploy-preview-412--material-ui-x.netlify.app/components/data-grid/. You can check this performance test, it becomes like the storybook (take about 8s to be ready).
- 📚 Could you add a description to the pull request? This would help to explain the issue, the solution, the options that were considered. If we do it orally, we will cover the problem on the surface. We won't also be able to go back to it in x months. Or even link to new developers joining the team. I think that the bigger the pull request is, the more relevant this feedback is.
- 🐛 The resizing feature is no longer working.
- 🚀 In the sorting feature, restoring the default sort order doesn't longer feel instant. It goes from 50ms to 500ms (on my machine)
- ⚛️ I think that changes in end-to-ends tests for refactorization are always something to be extremely cautious with. If the tests are well written and if the refacto implements the same behavior, they shouldn't be any changes. I have seen changes in the test that suggests regressions (skip, sleep, tests no longer act-synchronous).
- ⚛️ Some parts of the grid reducer logic seem not idiomatic to React, it might cause bugs. See the second review to have more info.
- 🚀 Click the select all rows freeze the whole UI for ~5s
- 🐛 The keyboard logic is broken. When you use it with two data tables on the same page, it jumps between the two. The focus leaks
- 🐛 Once you start using the keyboard logic, the virtualization becomes unresponsive. There are major white areas.
- 🐛 The keyboard logic is unresponsive, it takes 250ms easily to handle a press. It seems to be an infinite ref loop issue.
I have run all my tests with the main demo.
I'm having a look at what's going on with 1. 5. 6. and 7, see if I can help.
- and 7. handled in Performance issue dtassone/material-ui-x#3
internalOptions.autoHeight, | ||
internalOptions.headerHeight, | ||
internalOptions.rowHeight, | ||
import useForkRef from '@material-ui/core/utils/useForkRef'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This import is invalid. It leads to bundling duplicate versions of the same modules (CJS + ESM, which harm bundle size).
import useForkRef from '@material-ui/core/utils/useForkRef'; | |
import { useForkRef } from '@material-ui/core/utils'; |
We will get an error once we enable the eslint rule back:
We also have this issue in the main repo, mui/material-ui#23159 expose some cases.
@@ -1,7 +1,6 @@ | |||
import * as React from 'react'; | |||
import { HashRouter, Route, Switch } from 'react-router-dom'; | |||
import styled, { createGlobalStyle } from 'styled-components'; | |||
import './app.less'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For any large pull requests. I think that we should strongly encourage to move any change that can be prune outside of it. For instance here, we go after fixing the build of the demo-app
. We can deliver value by fixing it independently from the refactoring. Then, we can rebase this pull request on the fix once it lands in master
.
const cellRef = React.useRef<HTMLDivElement>(null); | ||
|
||
React.useEffect(() => { | ||
if (hasFocus && cellRef.current) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cellRef.current
should always be defined, by contract with React.
if (hasFocus && cellRef.current) { | |
if (hasFocus) { |
if it's not, something is wrong in the core structure, better not hiding it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the initial value is null, and it gets defined after the component mount. So I can remove it and add a ! which won't change much.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
!
save bundle size but more importantly it allows us to not silently ignore the problem if, in a future refactorization, we forget to apply the ref correctly.
|
||
return <React.Fragment>{items}</React.Fragment>; | ||
}); | ||
}; | ||
ColumnHeaderItemCollection.displayName = 'ColumnHeaderItemCollection'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It has no impact, the component isn't memo or forward ref, if we do, better name the function to get bundle size once it lands in production.
ColumnHeaderItemCollection.displayName = 'ColumnHeaderItemCollection'; |
row, | ||
rowIndex, | ||
scrollSize, | ||
cellFocus, | ||
showCellRightBorder, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Best to keep the props sort ASC, more structure make it simpler to navigate it.
@@ -5,6 +5,7 @@ | |||
"declarationDir": "./dist", | |||
"module": "es6", | |||
"noImplicitAny": false, | |||
"noUnusedLocals": false, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"noUnusedLocals": false, |
Note that I normalize the tsconfig in #448.
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. | ||
# yarn lockfile v1 | ||
|
||
|
||
reselect@^4.0.0: | ||
version "4.0.0" | ||
resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.0.0.tgz#f2529830e5d3d0e021408b246a206ef4ea4437f7" | ||
integrity sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA== |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. | |
# yarn lockfile v1 | |
reselect@^4.0.0: | |
version "4.0.0" | |
resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.0.0.tgz#f2529830e5d3d0e021408b246a206ef4ea4437f7" | |
integrity sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA== |
@@ -17,7 +17,7 @@ | |||
"noImplicitThis": true, | |||
"noImplicitAny": false, | |||
"strictNullChecks": true, | |||
"noUnusedLocals": true, | |||
"noUnusedLocals": false, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"noUnusedLocals": false, | |
"noUnusedLocals": true, |
// eslint-disable-next-line mocha/no-skipped-tests | ||
xit('should throw if the rows has no id', function test() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// eslint-disable-next-line mocha/no-skipped-tests | |
xit('should throw if the rows has no id', function test() { | |
it('should throw if the rows has no id', function test() { |
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- 🐛 A new bug I have seen: If you add a
onChange
callback, it's called infinitely. For instance:
<DataGrid
page={page}
onPageChange={(params) => {
console.log('onchange')
setPage(params.page);
}}
pageSize={5}
pagination
{...data}
/>
I had a closer look at 6. I have left a few extra comments where relevant :).
I don't understand how the new state structure solves "the problem". From what I understand, we are missing two important parts of the equation:
- Updates across hook and components. How is
useGridReducer
different fromReact.useReducer
? It seems to behave identically (at the exception thatuseGridReducer
has a global imperative side effect).
Here is an example of what I mean by "the problem". TheuseColumnReorder()
needs to set in the state that the column field id Y is reordering. How will this notification ends re-rendering<ColumnHeaderItem>
(and only) so it can add the correct CSS class name? I see that we have anuseSelector
equivalent API to redux:useGridReducer
but it's not wired. Shouldn't we listen to the event emitter here? I assume the memo we have in place will prune the rendering. - The public API. How does it fit into [RFC] Change API state #190? For instance, controlled pagination. Forcing:
<DataGrid page={1}>
is not working, the page can be changed, from the internal state. It's not frozen on 1 as a developer would expect. The prop behaves like a default prop. A solution would probably start with something in this order:
diff --git a/packages/grid/_modules_/grid/hooks/features/pagination/usePagination.ts b/packages/grid/_modules_/grid/hooks/features/pagination/usePagination.ts
index 6af6f657..549697c4 100644
--- a/packages/grid/_modules_/grid/hooks/features/pagination/usePagination.ts
+++ b/packages/grid/_modules_/grid/hooks/features/pagination/usePagination.ts
@@ -99,9 +99,9 @@ export const usePagination = (apiRef: ApiRef): PaginationProps => {
dispatch(setPaginationModeActionCreator({ paginationMode: options.paginationMode! }));
}, [apiRef, dispatch, options.paginationMode]);
- React.useEffect(() => {
- setPage(options.page != null ? options.page : 1);
- }, [options.page, setPage]);
+ if (options.page != null) {
+ setPage(options.page);
+ }
React.useEffect(() => {
if (!options.autoPageSize && options.pageSize) {
For the uncontrolled mode. Will we have a global defaultState
prop? Will we allow to reduce all the events with a stateReducer
prop?
For the controlled mode. Will we allow developer to force a state
prop? Will we add a onStateChange
prop?
apiRef: ApiRef | undefined, | ||
selector: (state: any) => State, | ||
) => { | ||
const [state, ,] = useGridState(apiRef!); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const [state, ,] = useGridState(apiRef!); | |
const [state] = useGridState(apiRef!); |
Refactored state to attach it to apiRef. Performance issues will be treated in following PRs * WIP state refactoring on pagination * fix merging issues * WIP working on the rowsReducer and global state * fixes state refactoring finalizing api * refactored grid reducer * fix issue with state and cleanup * fix state and added sortedSelctor for viewport * prettier * fix state virtualisation * small refactoring with selector * rollback lint rules * remove options prop to useGridSelector * prettier * cleanup commented code * fix pagination and rendering issues * fix sorting and refactored hooks props * Refactored useSorting to new gridState * rebased and fix issues * cleanup * prettier * fix test * rebased * fix demo app * small refactoring on header item * fix dependency cycle * fix index * prettier * removed unused fn * fixing test * small refactoringg * prettier * perf improvements and keyboard refactoring * improve perf and fix keyboard and test * move virtualisation folder * prettier * refactor useComponents and useEvents * yarn docs ts formatted * fix demos and issue with resizing * fix types in doc * small fix prettier * fix rows perf, and prettier * fix dependency array * fix prettier * restored rowIndex
No description provided.