Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ForwardRef error with typescript and react-native

I'm getting a ts error when using forwardRef

// [ts] Property 'forwardRef' does not exist on type 'typeof React'.
const MyComponent = React.forwardRef((props: Props, ref: any) => ...

In React Native the parent component is throwing this error:

Invariant Violation: Element type is invalid: expected a string (for build-in components) or a class/function (for composite components) but got: object

Any idea on how to solve it?

like image 798
bernatfortet Avatar asked May 10 '18 00:05

bernatfortet


People also ask

What is forwardRef in React native?

React forwardRef is a method that allows parent components pass down (i.e., “forward”) refs to their children. Using forwardRef in React gives the child component a reference to a DOM element created by its parent component. This then allows the child to read and modify that element anywhere it is being used.

What is difference between useRef and forwardRef?

The forwardRef hooks allows React users to pass refs to child components. The ref can be created and referenced with useRef or createRef and then passed in a parent component. Using forwardRef instead of useRef is useful when a ref needs to be accessed in a parent component.

How do I import forwardRef into React?

On this case, we need to change the Input Component to use the forwardRef. import React, { forwardRef } from "react"; const Input = (props, ref) => <input ref={ref} type="text" style={style} />; export default forwardRef(Input);


Video Answer


1 Answers

According to the definitions:

function forwardRef<T, P = {}>(Component: RefForwardingComponent<T, P>): ComponentType<P & ClassAttributes<T>>;
interface RefForwardingComponent<T, P = {}> {
    (props: P & { children?: ReactNode }, ref?: Ref<T>): ReactElement<any> | null;
    propTypes?: ValidationMap<P>;
    contextTypes?: ValidationMap<any>;
    defaultProps?: Partial<P>;
    displayName?: string;
}

ref is an optional argument, try the following:

Inside a class create a ref object with a type parameter equal to your desired target (in my case div but View also works in react-native)

private divRef: React.RefObject<div> = React.createRef();

In the interface that represents the props for the forwarded component expose it as an optional property

interface Props {
  ref?: React.RefObject<div>;
}

Declare the forwarded component with the type React.ComponentType

const ComponentWithForwardedRef: React.ComponentType<Props> = 
  React.forwardRef((props: Props, ref?: React.Ref<div>) => (
    <div ref={ref}>{props.message}</div>
  ));

When an instance of the component with the forwarded ref is created send the created ref object as a prop

<ComponentWithForwardedRef ref={this.divRef} />

All in one:

import * as React from "react";
import { render } from "react-dom";

interface Props {
  message: string;
  ref?: React.RefObject<div>;
}

const ComponentWithForwardedRef: React.ComponentType<Props> = 
  React.forwardRef((props: Props, ref?: React.Ref<div>) => (
    <div ref={ref}>{props.message}</div>
  ));

class App extends React.Component<Props> {
  private divRef: React.RefObject<div> = React.createRef();

  public componentDidMount() {
    const div = this.divRef.current;
    // check the console!
    console.log(div);
  }

  public render() {
    return (
      <ComponentWithForwardedRef ref={this.divRef} {...this.props} />
    )
  }
}

render(<App message="hello world" />, document.getElementById("root"));

Link for posterity: https://codesandbox.io/s/6v152q394k

Dependencies (reference purposes)

"@types/react": "^16.3.11",
"@types/react-native": "^0.55.19",
"react-native": "0.55.2",
"typescript": "^2.8.1"
like image 56
Mauricio Poppe Avatar answered Oct 26 '22 02:10

Mauricio Poppe