-
-
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
[DataGridPro] Fix onColumnWidthChange
being called twice on autosize
#12140
[DataGridPro] Fix onColumnWidthChange
being called twice on autosize
#12140
Conversation
Deploy preview: https://deploy-preview-12140--material-ui-x.netlify.app/ |
if (previousMouseClickEvent.current) { | ||
const prevTimeStamp = previousMouseClickEvent.current.timeStamp; | ||
const prevClientX = previousMouseClickEvent.current.clientX; | ||
const prevClientY = previousMouseClickEvent.current.clientY; | ||
if ( | ||
nativeEvent.timeStamp - prevTimeStamp < 300 && | ||
nativeEvent.clientX === prevClientX && | ||
prevClientY === nativeEvent.clientY | ||
) { |
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.
Can you explain the logic behind this logic?
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.
So overall logic is.
Mouse double click is combination of 2 mouseup and mousedown event.
But according to our previous logic whenever mousedown event used to occur we add the event listeners to listen mouseup event and resize according.
This logic had a collision with the mouse double click so just to distinguish between mouse double click and mouse up/ mouse down event I compared the time interval between mouse down and mouseup event and their coordinate if it is same this directly means user wants to do double click.
Hope I am able to explain this
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.
@romgrk added proper comment for understanding the code
packages/x-data-grid-pro/src/hooks/features/columnResize/useGridColumnResize.tsx
Outdated
Show resolved
Hide resolved
2f3b2ea
to
5c35631
Compare
8b481c4
to
53f884a
Compare
53f884a
to
e3b0d63
Compare
@romgrk Added the test case if you can review |
packages/x-data-grid-pro/src/hooks/features/columnResize/useGridColumnResize.tsx
Outdated
Show resolved
Hide resolved
I seem to be able to reproduce the original issue with this PR: https://codesandbox.io/p/sandbox/mui-mui-x-x-data-grid-forked-f9skhw?file=%2Fsrc%2Fdemo.tsx%3A113%2C1 |
It seems this is private I can't access this |
Updated permissions. |
Basically React state updates are asynchronous but this element key is the DOM element but state update hasn't yet propagated to the DOM before being accessed that's the reason we are getting the old value in the element key but new value elsewhere like in key colDef and width. If you have any idea how in MUI we can pass the callback function to the setState so that I can get the latest dom element because I think current call signature of setState doesn't allow this. |
0e5732d
to
4bcd99b
Compare
Only way that I can figure out as of now to access the DOM element after state change is done in this commit But here I have to disable the eslint because I have to trigger the useEffect on change of isAutosizingRef.current but Mutable values like 'isAutosizingRef.current' aren't valid dependencies because mutating them doesn't re-render the component . this disabling of the eslint will not cause any bug in future as I just need this to access the updated dom element. To confirm this I updated the test case as well. @romgrk if you can suggest any better approach |
packages/x-data-grid-pro/src/tests/columns.DataGridPro.test.tsx
Outdated
Show resolved
Hide resolved
Wouldn't it be better to dispatch a |
Problem with this approach is when we disptach the |
But the widths are available at |
here you can see we have to publish three key element, colDef, width here key element is the DOM element which is doesn't get updated immediately that the main reason I have to use useEffect to access the updated element after the DOM updation. In your example also (https://codesandbox.io/p/sandbox/mui-mui-x-x-data-grid-forked-f9skhw?file=%2Fsrc%2Fdemo.tsx%3A76%2C6) the element.clientWidth was actually wrong not params.width. |
I hope this is clear or should I make one short video explaining this |
packages/x-data-grid-pro/src/hooks/features/columnResize/useGridColumnResize.tsx
Outdated
Show resolved
Hide resolved
ed1588f
to
d56332d
Compare
packages/x-data-grid-pro/src/hooks/features/columnResize/useGridColumnResize.tsx
Outdated
Show resolved
Hide resolved
c895e5c
to
57a4903
Compare
|
||
newColumns.forEach((newColumn) => { | ||
const width: number = newColumn.width as number; | ||
apiRef.current.publishEvent('columnWidthChange', { | ||
element: apiRef.current.getColumnHeaderElement(newColumn.field), | ||
colDef: newColumn, | ||
width, | ||
}); | ||
}); |
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 will trigger for all columns regardless of if they have changed. You have the original columns in columns
.
You can avoid typings like this, the inference knows it's a number:
const width: number = newColumn.width as number;
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 doing something wrong this implementation is correct.
let me Explain in detail
There are two possibility of calling autosizeColumns function
- through doubleClick event Listener https://github.com/mui/mui-x/blob/next/packages/x-data-grid-pro/src/hooks/features/columnResize/useGridColumnResize.tsx#L743 from here handleColumnSeparatorDoubleClick calls the autosizeColumns and over here it pass the exact column which is being resized
- At the time of mounting when user pass autoResizeOnMount prop https://github.com/mui/mui-x/blob/next/packages/x-data-grid-pro/src/hooks/features/columnResize/useGridColumnResize.tsx#L716
here each of the column is being resized on mounting
In our case to solve this bug we only need to concentrate on case 1 when the autosizeColumns is called on double click.
So on double click event from https://github.com/mui/mui-x/blob/next/packages/x-data-grid-pro/src/hooks/features/columnResize/useGridColumnResize.tsx#L661
we get only one column that needs to be resized and we need not check on all the columns.
Now in case 2 when autOResizeOnMount is called in that case all the columns should be resized and we need to decide whether to publish event or not.
So from both the case we can figure it out that either all of the column will be resized or only 1 will be resized.
if we want to disable the event publish on all column resize (case 2) we just need to add one condition
if (userOptions?.columns) {
newColumns.forEach((newColumn) => {
const width = newColumn.width;
apiRef.current.publishEvent('columnWidthChange', {
element: apiRef.current.getColumnHeaderElement(newColumn.field),
colDef: newColumn,
width,
});
});
}
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.
There is no need for an if
guard, just check the array and dispatch one event for each column that actually changed. Compare newColumn.width !== columns[index].width
in the .forEach
loop to figure out which ones changed.
The autosize function is part of the public API and can be called programatically with any number of columns.
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.
Okk then we need to consider this I thought it is not the public api
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.
Done
onColumnWidthChange
being called twice on autosize
Fixes #12005