Re this issue: https://github.com/reduxjs/react-redux/issues/1118
After rereading the react redux docs, the reason I thought withRef could only be used with connectAdvanced is because withRef only appears under [connectOptions] for connectAdvanced, and not regular connect. Had I read more carefully about connect I would've seen that it's a wrapper around connectAdvanced but I don't think it's obvious that withRef/forwardRef can be passed to just connect as it's not under [options]
Still a bit vague especially if I am approaching react-redux for the first time and trying to upgrade the codebase of an old project, for instance. Where do I need to use it and how can I pass it?
Does this work?
export default connect(
mapStateToProps,
mapDispatchToProps,
options: {
forwardRef: true,
},
)(MyComponent);
Or is it something like this?
export default connect(
mapStateToProps,
mapDispatchToProps,
forwardRef: true,
)(MyComponent);
Or even this?
export default connect(
mapStateToProps,
mapDispatchToProps,
{ forwardRef: true },
)(MyComponent);
@luigimannoni : please look at the API docs more carefully:
https://react-redux.js.org/api/connect
The signature is:
function connect(mapStateToProps?, mapDispatchToProps?, mergeProps?, options?)
Well, I have tried and it does not work well at all:
import React, { forwardRef } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import {
NavigationContainer as NavigationContainerDefault,
} from '@react-navigation/native';
function NavigationContainer({ theme, ...rest }) {
return (
<NavigationContainerDefault theme={theme} {...rest} />
);
}
NavigationContainer.propTypes = {
/** @ignore */
theme: PropTypes.object.isRequired,
/** Settings allow you to use other icons than MaterialCommunityIcons */
settings: PropTypes.object,
};
NavigationContainer.defaultProps = {
settings: undefined,
};
const mapStateToProps = (state) => ({
theme: state.layout.themes[state.preferences.colorScheme],
});
const connectAndForwardRef = (
mapStateToProps = null,
mapDispatchToProps = null,
mergeProps = null,
options = {},
) => (component) => connect(
mapStateToProps,
mapDispatchToProps,
mergeProps,
{
...options,
forwardRef: true,
},
)(forwardRef(component));
const ConnectedNavigationContainer = connectAndForwardRef(mapStateToProps)(NavigationContainer);
export default ConnectedNavigationContainer;
This result in :
import React, { forwardRef } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import {
NavigationContainer as NavigationContainerDefault,
} from '@react-navigation/native';
function NavigationContainer({ theme, ...rest }) {
return (
<NavigationContainerDefault theme={theme} {...rest} />
);
}
NavigationContainer.propTypes = {
/** @ignore */
theme: PropTypes.object.isRequired,
/** Settings allow you to use other icons than MaterialCommunityIcons */
settings: PropTypes.object,
};
NavigationContainer.defaultProps = {
settings: undefined,
};
const mapStateToProps = (state) => ({
theme: state.layout.themes[state.preferences.colorScheme],
});
const connectAndForwardRef = (
mapStateToProps = null,
mapDispatchToProps = null,
mergeProps = null,
options = {},
) => (component) => connect(
mapStateToProps,
mapDispatchToProps,
mergeProps,
{
...options,
forwardRef: true,
},
)(forwardRef(component));
const ConnectedNavigationContainer = connectAndForwardRef(mapStateToProps)(NavigationContainer);
export default ConnectedNavigationContainer;
Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
@kopax you can't give a ref to a function component, you need to export it as a class
I solved it with a function component..you need to stack useRef in connect and with the function.
You should avoid class @dereknelson
I solved it with a function component..you need to stack useRef in connect and with the function.
You should avoid class @dereknelson
Hi @kopax ! Do you have any exemple please ?
By stack I mean wrap your component with forwardRef as stated in reactjs documentation and also use the connect option with forwardRef true.
Try with a simple component. Not all components from 3rd party libraries handle it correctly. Try with one of your own as I said and it will work
A working solution with a functional component and connect :
const YourConnectedFC: FC = forwardRef((props, ref) => {
<Input ref={ref} />
});
export default connect(
null, // mapStateToProps
null, // mapDispatchToProps
null, // mergeProps
{ forwardRef: true }, // options
)(YourConnectedFC);
Exactly, bravo:)
A working solution with a functional component and connect
And how would this work with class components?
Just in case anyone is wondering with the @adrienlamotte example, you should still be able to pass along mapStateToProps and mapDispatchToProps as normal
const YourConnectedFC: FC = forwardRef((props, ref) => {
<Input ref={ref} />
});
export default connect(
mapStateToProps // pass these props to YourConnectedFC
mapDispatchToProps // pass these dispatch props to YourConnectedFC
null, // mergeProps
{ forwardRef: true }, // options
)(YourConnectedFC);
Most helpful comment
A working solution with a functional component and connect :