-
-
Notifications
You must be signed in to change notification settings - Fork 10.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
Use new forwardRef API in withRouter HOC #6056
Comments
@sanniassin The issue with using |
@pshrmn It should be easy to check if |
We're dealing with this on react-redux as well: reduxjs/react-redux#914 I think it's mainly about forwarding in the ref properly, not anything to do with BC support. |
I just decided to move to the
as the object being passed as console.log('MyWrappedComponent=', MyWrappedComponent);
// MyWrappedComponent= {$$typeof: Symbol(react.forward_ref), render: ƒ}
<Route path="/myPath" component={MyWrappedComponent} /> Is there any workaround that could be used to forward refs to Components wrapped by a HOC while simultaneously having functional routing? |
@jathanasiou I have the same problem. Did you find a solution? |
@kevinL5 It's been a while since I looked into this matter but I think I had partial success with passing the refs through my outer HOCs like so: export default function outerHOC() {
return function(WrappedComponent) {
return class Better extends React.Component {
render() {
// ...
return <WrappedComponent passedRef={this.props.passedRef} { ...this.props}/>
}
}
}
}
// unlike the Better HOC, this always wraps MyActualBaseComponent
export default function innerHOC() {
return function(WrappedComponent) {
return class Stronger extends React.Component {
render() {
// ...
return <WrappedComponent ref={this.props.passedRef} { ...this.props}/>
}
}
}
}
class MyActualBaseComponent extends React.Component {/*...*/}
export outerHOC()(innerHOC()(MyActualBaseComponent))
import BetterStronger from './MyActualBaseComponent'
class IndexControlComponent extends React.Component {
constructor(props) {
super(props)
this.neededRef = React.createRef()
}
render() {
const betterStronger = <BetterStronger passedRef={this.neededRef} {/*some props*/} />
}
needyFunction () => { // needs to control the wrapped MyActualBaseComponent instance
this.neededRef.current.doSomethingBetter()
this.neededRef.current.doSomethingStrong()
}
// ...
} It is a very hacky workaround however. Ideally we should try to avoid using refs with HOCs until this issue is resolved on react-router. |
Same problem with react-router using forwardRef
Workaround for now is to use the render prop of the Route component instead of the component prop: |
Yes, we should update We will fix this in version 5 when we upgrade our dep to React 16.7+. |
After much searching, I ended up creating a const withForwardingRef = <Props extends {[_: string]: any}>(BaseComponent: React.ReactType<Props>) =>
React.forwardRef((props, ref) => <BaseComponent {...props} forwardedRef={ref} />);
export default withForwardingRef; usage: const Comp = ({forwardedRef}) => (
<button ref={forwardedRef} />
)
const MyBeautifulComponent = withForwardingRef<Props>(Comp); // Now Comp has a prop called forwardedRef usage of usage: <MyBeautifulComponent ref={someRef} /> |
I see that v5 is out now (https://reacttraining.com/blog/react-router-v5/), but I'm struggling to find any documentation on how to use forwardRef and withRouter() together. Can anyone help? |
@esellin We haven't bumped the React version in 5.0, so we can't yet support forwardRef. |
I just renamed the |
This also applies to
|
@charlax And this is why the section describes a workaround. We even explicitly document it for react-router: https://material-ui.com/components/links/#third-party-routing-library |
Indeed! I knew about this page but did not think to look it up when using |
Finally, I have done this way! this will work for sure
|
As suggested in original SO question, here is a version built on @ranjith-s work, a bit simpler and that supports const withRouterAndRef = Wrapped => {
const WithRouter = withRouter(({ forwardRef, ...otherProps }) => (
<Wrapped ref={forwardRef} {...otherProps} />
))
const WithRouterAndRef = React.forwardRef((props, ref) => (
<WithRouter {...props} forwardRef={ref} />
))
const name = Wrapped.displayName || Wrapped.name
WithRouterAndRef.displayName = `withRouterAndRef(${name})`
return WithRouterAndRef
} |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. |
I think it is easier to create your own component like this import React from 'react';
import { Link as MaterialLink } from '@material-ui/core';
import { Link as RouterLink } from 'react-router-dom';
export default function (props) {
const MiddlewareLink = React.forwardRef((props, ref) => <RouterLink innerRef={ref} {...props} />);
return <MaterialLink component={MiddlewareLink} {...props} />;
} |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. |
I guess this can be closed anyway since |
React 16.3 is out and now we have an "official" way to pass ref through HOCs with new forwardRef API. Would you like to use it as a replacement for
wrappedComponentRef
prop to make wrapping transparent for parent components?Can submit a PR.
The text was updated successfully, but these errors were encountered: