Do you want to request a _feature_ or report a _bug_?
Bug
What is the current behavior?
When I updated to the latest version of react-redux, I started seeing the following warning on many of my connected components.
react-dom.development.js:506 Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
React doesn't allow refs on functional components, so any components that were accessed with a ref in past react-redux versions are now broken.
What is the expected behavior?
My connected components that were previously exposed with refs would still be able to have a ref.
Which versions of React, ReactDOM/React Native, Redux, and React Redux are you using? Which browser and OS are affected by this issue? Did this work in previous versions of React Redux? react v.16.8.6, react-dom v.16.8.6, react-redux v.7.0.3
First, function components cannot have refs.
With React-Redux specifically:
withRef: true option to connect(), put a ref on the Connect(MyComponent) wrapper, and then call wrapperComponent.getWrappedInstance()forwardRef : true option to connect(), and the ref that you put on the Connect(MyComponent) wrapper will actually be the instance of MyComponentIf you are _not_ supplying the forwardRef option in v6/7, then I would expect the ref to be applied to the internal wrapper component, which is now a function component, and thus you're getting that error message.
So, make sure you're passing {forwardRef : true} to connect(), and things should work okay.
Yes. I intended to access the internal wrapper component, and I was previously on v5.
If you are not supplying the forwardRef option in v6/7, then I would expect the ref to be applied to the internal wrapper component, which is now a function component, and thus you're getting that error message.
I guess I will have to refactor some code to get it to work the same way.
Basically, change withRef to forwardRef, and then delete the .getWrappedInstance() part of componentRef.getWrappedInstance(). componentRef is your own component now.
@markerikson I am curious to know why forwardRef: true option in not enabled by default when doing react- redux connect or maybe even a warning can be shown by react-redux that unless forwardRef: true is given the ref won't connect. If it is ok to do so, then I would love to work on this
There is a performance penalty and most folks don't need it.
Yep. It's an extra layer of wrapping, and refs are _very_ rarely used.
ok In that case, if the connected component detects that a ref is being passed, then atleast it should show a warning that unless forwardRef: true option is given the ref won't be connected. I am saying this because yesterday I lost around 3 hours of work, wondering why my refs are not getting a value.
If ok, then I would love to work on this .
Refs are never sent as props to the component, so it's not possible to know if your caller has used them or not.
Oh interesting. But in that case how does the forwardRef: true option works ?
By adding that extra wrapping layer I talked about, through use of React.forwardRef.
Oh interesting. But in that case how does the forwardRef: true option works ?
@sktguha forwardRef: true is an option passed in the 4th argument of the connect function.
function connect(mapStateToProps?, mapDispatchToProps?, mergeProps?, options?)
@markerikson In that case in dev mode , we can always use the extra wrapping layer and can read the ref argument's current value to detect if a ref is passed. I have got a basic working example here https://codesandbox.io/s/react-playground-kmv1c?file=/index.js
If you're using refs, you want them to work in both dev and prod. You don't want it to work automatically in development and then have it break when you go to production. That would be extremely frustrating behavior.
no no I didn't mean that. what I mean is that in dev mode we always wrap in React.forwardRef and detect
if (ref.current is truthy and forwardRef option is not true ) {
then we show the warning
}
But in prod for performance reasons we don't wrap in forwardRef
I really have no idea what problem you're trying to solve here. We're not planning on making any changes to this behavior.
well if I pass a ref to a component that is a connected, by default the ref doesn't get a value unless the forwardRef option is given in connect. So I want to detect if a ref is passed in and forwardRef option is not given, then I want to show a warning to the developer. I can elaborate if it's not clear.
@sktguha I don't think redux should be checking ref values. It could have unintended side effects and then everyone's dev environment would take a performance hit. React already gives you a warning if forwardRef is missing, and the forwardRef option is covered in the redux documentation.
Yep. As I said, no plans to change this.
Most helpful comment
First, function components cannot have refs.
With React-Redux specifically:
withRef: trueoption toconnect(), put arefon theConnect(MyComponent)wrapper, and then callwrapperComponent.getWrappedInstance()forwardRef : trueoption toconnect(), and therefthat you put on theConnect(MyComponent)wrapper will actually be the instance ofMyComponentIf you are _not_ supplying the
forwardRefoption in v6/7, then I would expect the ref to be applied to the internal wrapper component, which is now a function component, and thus you're getting that error message.So, make sure you're passing
{forwardRef : true}toconnect(), and things should work okay.