Skip to content

React 16.3+ forwardRef component #48

@Cap32

Description

@Cap32

React 16.3+ forwardRef() will return a new component (type is object) that contains a render function and a $$typeof Symbol, and these should not be copied, otherwise may cause some bug

Example to reproduce

import React, { Component, createRef, forwardRef } from 'react';
import hoistStatics from 'hoist-non-react-statics';

function hoist(WrappedComponent) {
	return function createHoistedComponent(TargetComponent) {
		const HoistedComponent = forwardRef((props, ref) => (
			<TargetComponent {...props} forwardedRef={ref} />
		));

		if (WrappedComponent) {
			HoistedComponent.displayName = `hoisted(${WrappedComponent.displayName})`;
			hoistStatics(HoistedComponent, WrappedComponent /* , { render: true } */);
		}

		return HoistedComponent;
	};
}

function extraPropsHoc(extra) {
	return (WrappedComponent) => {
		@hoist(WrappedComponent)
		class Bar extends Component {
			render() {
				const { forwardedRef, ...props } = this.props;
				return <WrappedComponent {...props} {...extra} ref={forwardedRef} />;
			}
		}
		return Bar;
	};
}

@extraPropsHoc({ foo: 'foo' })
@extraPropsHoc({ bar: 'bar' })
class Foo extends Component {
	static displayName = 'Foo';

	log() {
		console.log('this.props', this.props);
	}

	render() {
		return <h1>Hello</h1>;
	}
}

export default class App extends Component {
	ref = createRef();

	componentDidMount() {
		this.ref.current.log();
	}

	render() {
		return <Foo ref={this.ref} />;
	}
}

Result

this.props {bar: "bar"}

Expect

this.props {foo: "foo", bar: "bar"}

If I uncomment hoistStatics(HoistedComponent, WrappedComponent /* , { render: true } */), it will work as expected.

Env

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions