-
-
Notifications
You must be signed in to change notification settings - Fork 32.3k
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
[RFC] Refs in v4 #14415
Comments
Allow ref on all components. RootRef should be already deprecated since it's warned in strict mode. When fragment refs will come we can't know. |
|
That would awesome. Will force users to upgrade react though. We could also use hooks to get rid from cloneElement which failed for me a few times when I need to wrap MenuItem. |
Yes, because we have to use
The more interesting question would be "by how much" since any added behavior slows it down. I remember a discussion about this concerning forwardRef in react-redux and the gist was basically that while it was slower it wasn't because of
I had the same issue originally but I'm comfortable with it now. The fact that
What do hooks solve WRT to |
export const Menu = React.forwardRef((props, ref) => {
const [open, setOpen] = React.useState(false);
return (
<div ref={ref} onClick={() => setOpen(v => !v)}>{open ? 'open' : 'closed'}</div>
);
}); |
What do hooks solve here with regards to |
You don't need additional component wrapper like with classes. |
The usage of state in your example is arbitrary. You picked one feature of classes Try not to think about any specific implementation detail here. The original point
did not adress the concern of this issue. We already have function components that do not use hooks. What could you achieve with hooks in function components that solves any issue with refs? For example using |
My point was that hooks works inside of forwardRef function. So performance case you mentioned before is solved. I believe you won't use You will not end up with runtime warning. That's the point of forwardRef, isn't it? |
Probably if we actually port class components to function components. My statement was only made in the context of "given a component: what perf implication has forwardRef" which especially applies to already existing function components. But I think you implied that we wouldn't wrap those in
Maybe. I haven't seen any benchmarks comparing class components with function components + hooks though.
Exactly. This is the discussion we have: use |
I have looked into the performance implication. It's not significant. I think that we can ignore the problem. I have tried the following: function NakedButton(props) {
return <button type="button" {...props} />;
}
class HocButton extends React.Component {
state = {};
render() {
return <NakedButton {...this.props} />;
}
}
const ForwardRef = React.forwardRef((props, ref) => <button ref={ref} type="button" {...props} />);
suite
.add('NakedButton', () => {
ReactDOMServer.renderToString(<NakedButton>Material-UI</NakedButton>);
})
.add('ForwardRef', () => {
ReactDOMServer.renderToString(<ForwardRef>Material-UI</ForwardRef>);
})
.add('HocButton', () => {
ReactDOMServer.renderToString(<HocButton>Material-UI</HocButton>);
})
.on('cycle', event => {
console.log(String(event.target));
})
.run(); It outpus the following:
|
Good to know. |
Do we have any concern left to address? |
I don't think so. My primary concern was to consolidate all the concerns (and gather my own thoughts). If we implement this then #13394 should be resolved completely. Just looks better on paper to be "strict mode compliant". |
Alright, let's execute it then :) |
Adds explicit documentation to `https://material-ui.com/api/*` about ref forwarding. Requires #15131 to not report false positives. Finishes one point in #14415.
Close #14415 --- TODO: - [x] ClickAwayListener child ref (and derived components) - [x] ref forwarding in "API Design Approach" - [x] https://next.material-ui.com/getting-started/faq/#how-can-i-access-the-dom-element Co-authored-by: Matt <github@nospam.33m.co> Co-authored-by: Olivier Tassinari <olivier.tassinari@gmail.com>
💥 |
refs in v3
ref
e.g.<Button ref={handleRef} />
but allowinnerRef
for every componentPaper
orBackdrop
are function components and can therefore not hold refs. It will trigger a runtime warning.withStyles
from@material-ui/core
does not forward refs fromref
butinnerRef
.refs
can be problematic if multiple HOCs are used. E.g. Usingstyled-components
to style material-ui components will preventinnerRef
from being passed to the inner material-ui component.Proposal
explicitly document
ref
Couple of alternatives:
withStyles
). This will break in v4 if [styles] Improve ref forwarding #13676 is acceptedref
on all of our components. If the DOM node is requiredRootRef
should be used.The type declarations follow from the documentation.
ref
in v4With #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 holdref
(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 aref
to an abstractHTMLElement
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 imperativefocus
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 allowsref
(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
ref
on all components i.e. useref
at your own risk. PreferRootRef
if you need the DOM nodeRootRef
will triggerfindDOMNode
deprecation warningsref
behavior for inner components.ref
behavior on actual component will change though with [styles] Improve ref forwarding #13676.findDOMNode
ref
on all components. Interface it as a abstractHTMLElement
Confirmed
Currently missing (strike through means not applicable, some might already work but are not picked up by our docs generator)
[ ] TouchRipple.js(need imperative handle)[ ] ClickAwayListener.jsno host component rendered[ ] CssBaseline.jsno host component rendered[ ] Fade.jsno host component rendered[ ] Grow.jsno host component rendered[ ] Hidden.jsno host component rendered[ ] ListItemAvatar.jsno host component rendered[ ] NoSsr.jsno host component rendered[ ] Portal.jsno host component rendered[ ] RootRef.jsno host component rendered[ ] Zoom.jsno host component rendered[ ] Slide.jsno host component rendered[ ] Tooltip.jsRenders children as root, PopperProps available[ ] 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 priorityResources
RootRef
/cc @mui-org/core-contributors
The text was updated successfully, but these errors were encountered: