Skip to content
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

Checkbox column appended instead of prepended in concurrent mode #1562

Closed
eps1lon opened this issue May 4, 2021 · 9 comments
Closed

Checkbox column appended instead of prepended in concurrent mode #1562

eps1lon opened this issue May 4, 2021 · 9 comments
Labels
bug 🐛 Something doesn't work component: data grid This is the name of the generic UI component, not the React module!

Comments

@eps1lon
Copy link
Member

eps1lon commented May 4, 2021

If you can point me to the code that's responsible for inserting the column I can take a look to understand what's going wrong if you want.

Current Behavior 😯

When using <DataGrid checkboxSelection /> the column containing the checkboxes is the last column in concurrent react.

screenshot of the current behavior

Expected Behavior 🤔

It should be the first column

screenshot of the expected behavior

Steps to Reproduce 🕹

https://codesandbox.io/s/datagrid-legacy-vs-concurrent-root-84z9o?file=/demo.js

Steps:

  1. Use react@experimental (currently 0.0.0-experimental-79740da4c)
  2. render <DataGrid rows={rows} columns={columns} pageSize={5} checkboxSelection />

Context 🔦

Reproducible in our docs: https://60906bee09db3300076bbe72--material-ui.netlify.app/components/tables/#DataTable (mui/material-ui#26107)

Your Environment 🌎

See codesandbox. For the docs see the details below.

`npx @material-ui/envinfo`
System:
    OS: Linux 5.4 Ubuntu 20.04.2 LTS (Focal Fossa)
  Binaries:
    Node: 12.20.0 - ~/.nvm/versions/node/v12.20.0/bin/node
    Yarn: 1.22.10 - /usr/bin/yarn
    npm: 6.14.8 - ~/.nvm/versions/node/v12.20.0/bin/npm
  Browsers:
    Chrome: 90.0.4430.72
    Firefox: 88.0
  npmPackages:
    @emotion/react: ^11.0.0 => 11.1.5 
    @emotion/styled: ^11.0.0 => 11.3.0 
    @material-ui/codemod:  5.0.0-alpha.30 
    @material-ui/core:  5.0.0-alpha.32 
    @material-ui/data-grid:  4.0.0-alpha.27 
    @material-ui/docs:  5.0.0-alpha.31 
    @material-ui/envinfo:  1.1.6 
    @material-ui/icons:  5.0.0-alpha.29 
    @material-ui/lab:  5.0.0-alpha.32 
    @material-ui/private-theming:  5.0.0-alpha.32 
    @material-ui/styled-engine:  5.0.0-alpha.26 
    @material-ui/styled-engine-sc:  5.0.0-alpha.26 
    @material-ui/styles:  5.0.0-alpha.32 
    @material-ui/system:  5.0.0-alpha.31 
    @material-ui/types:  6.0.0 
    @material-ui/unstyled:  5.0.0-alpha.32 
    @material-ui/utils:  5.0.0-alpha.31 
    @types/react: ^17.0.3 => 17.0.4 
    react: ^17.0.1 => 0.0.0-experimental-79740da4c 
    react-dom: ^17.0.1 => 0.0.0-experimental-79740da4c 
    styled-components:  5.2.3 
    typescript: ^4.1.2 => 4.2.4 

Order id 💳

N/A

@eps1lon eps1lon added bug 🐛 Something doesn't work component: data grid This is the name of the generic UI component, not the React module! labels May 4, 2021
@oliviertassinari
Copy link
Member

Oh wow, this one is amazing. I'm curious to see why. It could require changing the architecture if it surfaces a design assumption that doesn't hold.

@dtassone
Copy link
Member

dtassone commented May 6, 2021

TBH, I'm not sure why we always have to question the architecture of the grid every time there is a new issue.
It is probably the same kind of fix as strict mode...

Also changing the "architecture" at this stage would delay all the plans to go to beta, and stable.

Concurrent mode is in experimental stage, I don't think this issue is worth looking at this stage.
It could be automatically fixed in the stable version.

@oliviertassinari
Copy link
Member

oliviertassinari commented May 6, 2021

In my mind, "architecture" means the main pillars we depend on to account for the constraints of the real world and to shelter the features we are building around it.

For the support of strict mode, we had to shift a bit our approach. Concurrent mode is a significant implementation shift in React, it sets new constraints. I think that the eventuality that the current structure won't hold with these new constraints is not impossible. I didn't intend to say more.

I was about to make the same point 👍. The set of constraints that concurrent mode creates is not fixed, so maybe we have an issue right now, that will go away tomorrow (the inverse is also possible).

@oliviertassinari oliviertassinari added the on hold There is a blocker, we need to wait label May 6, 2021
@eps1lon eps1lon removed the on hold There is a blocker, we need to wait label May 20, 2021
@eps1lon
Copy link
Member Author

eps1lon commented Jun 13, 2021

Couple of things:

  1. Naming of hydrateColumns
    Hydration is a pretty well established term in React. However, I can't see what hydration has to do with this method. The checkbox column doesn't exist when hydrateColumns runs. So the column should probably already exists when hydrateColumns run and then you should document what is being "hydrated".
  2. Apply getDerivedStateFromProps pattern
    As far as I can tell you're updating state in useEffect in response to a change of props. You should apply the getDerivedStateFromProps with hooks pattern instead which gets rid of the cascading update that probably leads to the tearing we're seeing in React 18

@flaviendelangle
Copy link
Member

What would be the correct naming for hydrateColumns here ? From what I understand it's a pre-processing step on the columns.

@eps1lon
Copy link
Member Author

eps1lon commented Jul 5, 2021

This is on this weeks agenda. I should have a version of this behavior without tearing in v5. If that works as I think it does then I may even be able to write a lint rule that finds these "set state state in an effect" patterns. It seems to me these patterns are just applied out of convenience so we need to find a way to make the right pattern more convenient.

@eps1lon
Copy link
Member Author

eps1lon commented Jul 5, 2021

It seems like you've implemented your own statement managment solution. I've traced the state changes and they all end up in some ref reassignment (https://github.com/mui-org/material-ui-x/blob/2cf4818737a96b983222f3c5e32d89d3303fa313/packages/grid/_modules_/grid/hooks/features/core/useGridState.ts#L22-L22) that will ultimately block most know React patterns from working.

I'm fairly certain this is just derived state but due to the custom state managment you won't be able to unlock a lot of React's own perf optimizations (especially the ones coming with concurrent rendering).

This is painfully obvious by the fact that you need to use a forceUpdate helper so often.

Consider GridComponent. The user passes in columns but then we compute the columns with the checkbox and dispatch a change event. Either the user should just pass in the columns with checkbox (optionally with a helper like <GridComponent columns={withCheckbox(columns)} /> or the checkbox should just be part of some internal state that we derive from the columns props. But dispatching a change event even though nothing actually changes is a bit odd.

But mixing these together creates problems with component composition. I've seens this mistake repeat over and over again (latest example are the picker components). And we have this pretty well documented in React in the controlled/uncontrolled components pattern and the derived state pattern.

@oliviertassinari
Copy link
Member

oliviertassinari commented Aug 14, 2021

It's behaving correctly with v4.0.0-alpha.37: https://codesandbox.io/s/datagrid-legacy-vs-concurrent-root-forked-hkp39?file=/demo.js. We changed something along the way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 🐛 Something doesn't work component: data grid This is the name of the generic UI component, not the React module!
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants