- 
          
- 
                Notifications
    You must be signed in to change notification settings 
- Fork 32.7k
Description
refs in v3
- refs are not included in the API documentation on material-ui.com
- type declarations forbid refe.g.<Button ref={handleRef} />but allowinnerReffor every component- The latter is wrong in some cases. E.g. The inner components of PaperorBackdropare function components and can therefore not hold refs. It will trigger a runtime warning.
 
- The latter is wrong in some cases. E.g. The inner components of 
- withStylesfrom- @material-ui/coredoes not forward refs from- refbut- innerRef.- named props for refscan be problematic if multiple HOCs are used. E.g. Usingstyled-componentsto style material-ui components will preventinnerReffrom being passed to the inner material-ui component.
 
- named props for 
Proposal
explicitly document ref
Couple of alternatives:
- We could start by collecting what components allow this at the moment (basically every component wrapped in withStyles). This will break in v4 if [styles] Improve ref forwarding #13676 is accepted
- Disallow refon all of our components. If the DOM node is requiredRootRefshould be used.
The type declarations follow from the documentation.
ref in v4
With #13676 and the replacement of @material-ui/core/styles with @material-ui/styles as our internal styling solution <Button ref /> would return the ref to the inner component by default. In it's current state some components would loose the ability to hold ref (e.g. AppBar).
There is an argument to be made that ref inherently cause all sorts of problems in general. However I would argue that all of our components return some html element. Interfacing our components so that they only return a ref to an abstract HTMLElement should therefore cause no problems in the future. It doesn't bind us to any specific implementation (other than a html element). This allows e.g. layout computations if necessary or imperative focus which is what we use internally.
I'm in favor of enabling refs on all of our existing components. It allows for a simpler API where one doesn't have to look at the API docs for every single component and check if it allows ref (and then be annoyed because we didn't have your use case in mind). (Although TS users can be lazy and don't have to check API docs).
Summary
- Add explicit documentation
- Fix typescript declarations
- One of
- Disallow refon all components i.e. userefat your own risk. PreferRootRefif you need the DOM node- RootRefwill trigger- findDOMNodedeprecation warnings
 
- Don't change refbehavior for inner components.refbehavior on actual component will change though with [styles] Improve ref forwarding #13676.- users are stuck with findDOMNode
 
- users are stuck with 
- Allow refon all components. Interface it as a abstractHTMLElement- strict and concurrent mode viable for all current use cases
 
 
- Disallow 
Confirmed
- add explicit documentation
- fix typescript declarations
- add migration guide [docs] Document ref forwarding (requirements) #15298
- add prop-type if we require refs in the component
- forward refs for every component (started in [core] forward innerRef for certain components #14536)
Currently missing (strike through means not applicable, some might already work but are not picked up by our docs generator)
- AppBar.js
- Backdrop.js
- Avatar.js
- BottomNavigation.js
- BottomNavigationAction.js
- Breadcrumbs.js
- [ ] TouchRipple.js(need imperative handle)
- Card.js
- CardActionArea.js
- CardActions.js
- CardContent.js
- CardHeader.js
- CardMedia.js
- Checkbox.js
- CircularProgress.js
- [ ] ClickAwayListener.jsno host component rendered
- Container.js
- [ ] CssBaseline.jsno host component rendered
- Dialog.js
- DialogActions.js
- DialogContent.js
- DialogContentText.js
- DialogTitle.js
- Divider.js
- ExpansionPanel.js
- ExpansionPanelActions.js
- ExpansionPanelDetails.js
- ExpansionPanelSummary.js
- Fab.js
- [ ] Fade.jsno host component rendered
- FilledInput.js
- FormControl.js
- FormControlLabel.js
- FormGroup.js
- FormHelperText.js
- FormLabel.js
- Grid.js
- GridList.js
- GridListTile.js
- GridListTileBar.js
- [ ] Grow.jsno host component rendered
- [ ] Hidden.jsno host component rendered
- Icon.js
- IconButton.js
- Input.js
- InputAdornment.js
- InputLabel.js
- Link.js
- List.js
- ListItem.js
- [ ] ListItemAvatar.jsno host component rendered
- ListItemIcon.js
- ListItemSecondaryAction.js
- ListItemText.js
- ListSubheader.js
- Menu.js
- MenuItem.js
- MenuList.js
- MobileStepper.js
- NativeSelect.js
- [ ] NoSsr.jsno host component rendered
- OutlinedInput.js
- Paper.js
- Popper.js
- [ ] Portal.jsno host component rendered
- Radio.js
- RadioGroup.js
- [ ] RootRef.jsno host component rendered
- Select.js
- SnackbarContent.js
- Step.js
- StepButton.js
- StepConnector.js
- StepContent.js
- StepIcon.js
- StepLabel.js
- Stepper.js
- SvgIcon.js
- Switch.js
- Tab.js
- Table.js
- TableBody.js
- TableCell.js
- TableFooter.js
- TableHead.js
- TableRow.js
- TableSortLabel.js
- TextField.js
- Toolbar.js
- Typography.js
- [ ] Zoom.jsno host component rendered
- Badge.js
- Button.js
- Collapse.js
- Drawer.js
- LinearProgress.js
- [ ] Slide.jsno host component rendered
- Snackbar.js
- TablePagination.js
- [ ] Tooltip.jsRenders children as root, PopperProps available
- ButtonBase.js
- Chip.js
- InputBase.js
- Modal.js
- SwipeableDrawer.js
- Tabs.js
- Popover.js
- [ ] SpeedDialIcon.jslab has low priority
- [ ] Slider.jslab has low priority
- [ ] SpeedDialAction.jslab has low priority
- [ ] SpeedDial.jslab has low priority
- [ ] ToggleButton.jslab has low priority
- [ ] ToggleButtonGroup.jslab has low priority
Resources
/cc @mui-org/core-contributors