Skip to content
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

Update react-redux docs for forwardRef #1119

Closed
dereknelson opened this issue Dec 12, 2018 · 12 comments
Closed

Update react-redux docs for forwardRef #1119

dereknelson opened this issue Dec 12, 2018 · 12 comments

Comments

@dereknelson
Copy link

Re this issue: #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]

@timdorr
Copy link
Member

timdorr commented Jan 23, 2019

We've got this now: https://github.com/reduxjs/react-redux/blob/50883450079356e70828139e531303a962b85458/docs/api/connect.md#forwardref-boolean

@timdorr timdorr closed this as completed Jan 23, 2019
@luigimannoni
Copy link

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);

@markerikson
Copy link
Contributor

@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?)

@kopax
Copy link

kopax commented Mar 29, 2020

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()?

@dereknelson
Copy link
Author

@kopax you can't give a ref to a function component, you need to export it as a class

@kopax
Copy link

kopax commented Mar 29, 2020

I solved it with a function component..you need to stack useRef in connect and with the function.

You should avoid class @dereknelson

@adrienlamotte
Copy link

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 ?

@kopax
Copy link

kopax commented Apr 10, 2020

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

@adrienlamotte
Copy link

adrienlamotte commented Apr 11, 2020

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);

@kopax
Copy link

kopax commented Apr 11, 2020

Exactly, bravo:)

@derwaldgeist
Copy link

A working solution with a functional component and connect

And how would this work with class components?

@thathurtabit
Copy link

thathurtabit commented May 6, 2020

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);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants