Skip to content

Instantly share code, notes, and snippets.

@jamesreggio
Last active September 21, 2024 06:31
Show Gist options
  • Save jamesreggio/142215754ad06f375bd87657c6227ed8 to your computer and use it in GitHub Desktop.
Save jamesreggio/142215754ad06f375bd87657c6227ed8 to your computer and use it in GitHub Desktop.
Simple example usage of React.forwardRef()
// EmailInput wraps an HTML `input` and adds some app-specific styling.
const EmailInput = React.forwardRef((props, ref) => (
<input ref={ref} {...props} type="email" className="AppEmailInput" />
));
class App extends Component {
emailRef = React.createRef();
render() {
return (
<div>
<EmailInput ref={this.emailRef} />
<button onClick={() => this.onClickButton()}>
Click me to focus email
</button>
</div>
);
}
// `this.emailRef.current` points to the `input` component inside of EmailInput,
// because EmailInput is forwarding its ref via the `React.forwardRef` callback.
onClickButton() {
this.emailRef.current.focus();
}
}
@mehuljariwala
Copy link

mehuljariwala commented May 5, 2020

<input ref={this.emailRef} type="email" className="AppEmailInput" />
I can declare like this also but I am not getting what is the use of React.forwardRef

can you please explain this to me?

@GiuseppeMP
Copy link

<input ref={this.emailRef} type="email" className="AppEmailInput" />
I can declare like this also but I am not getting what is the use of React.forwardRef

can you please explain this to me?

This code means that var emailRef = React.createRef(); may ref input dom, because React.forwardRef pass it along the children elements.

@khainguyenvan
Copy link

khainguyenvan commented May 20, 2020

<input ref={this.emailRef} type="email" className="AppEmailInput" />
I can declare like this also but I am not getting what is the use of React.forwardRef

can you please explain this to me?

Forward ref means forward the control of some elements to outside (consumer) component. So the parent can controls something inside the forwardref (child) component. Something like the computer in your house and you want to control from your company, so you make a key/connection (ref) to access from your work, without the key (ref) you cannot do anything. Ordinarily, you design a function and pass to child as props. But with ref, it's multipurpose, you don't have to predefined any function, just use the event and value of the ref (element/dom). Be careful when the ref exist in the tree or not.

@mattmogford
Copy link

mattmogford commented Jun 3, 2020

I have this setup in react-native.
But since the last release(or 2), it has broken for me.
From parent, customRef.current now only contains

"_nativeTag": 145,
      "_children": [],
      "viewConfig": {...}

Any ideas on why?

@dheeraj-br
Copy link

<input ref={this.emailRef} type="email" className="AppEmailInput" />
I can declare like this also but I am not getting what is the use of React.forwardRef

can you please explain this to me?

Yes, i have the same question. can anyone mention the usecase of forwardRef that cant be achieved by sending refs as props? there must be a reason for introducing forwardRef

@zmeyc
Copy link

zmeyc commented Jul 23, 2020

@dheeraj-br ref won't appear in child component's props when the component is not wrapped in React.forwardRef. It's a special case like key, not a normal property.

@artem-malko
Copy link

@zmeyc but if we will pass it as refSomething, it will be in props) So, what the difference?)

@zmeyc
Copy link

zmeyc commented Jul 23, 2020

@artem-malko As I understand, in <Wrapper ref=...>, ref refers to wrapper component itself. I.e. React processes it and removes from props. If it's desirable to reference wrapped (child) component instead, it's possible to link wrapper's ref to child using forwardRef.

You're right that it's also possible to expose child's ref via a custom property, but this can be counter-intuitive for lib's users as name of the property can't be easily discovered. For example, if there's EnhancedInput wrapping <input>, users would probably expect that <EnhancedInput ref=... would reference actual <input> from where they can get the value etc and not the wrapper.

@artem-malko
Copy link

@zmeyc ok, thx)

@sreechu
Copy link

sreechu commented Aug 3, 2020

I feel this discussion also explains better - forwardRef function vs a custom ref
https://stackoverflow.com/questions/58578570/value-of-using-react-forwardref-vs-custom-ref-prop
We use both in our project and while the former offers a way to pass a reference to the inner elements (to the root element that actually appears in the HTML dom), the latter can provide a way to pass ones that you already have might have declared in the component that is calling another.
Example: Check out use-resize-observer package: https://github.com/ZeeCoder/use-resize-observer

@jonlepage
Copy link

jonlepage commented Dec 14, 2020

thanks work fine for my case !
here cool example for types and control a powerful componement

export const Box = React.forwardRef(
	/**
	 * @typedef {Object} FlexOption
	 * @property {React.CSSProperties['display']} [FlexOption.display]
	 * @property {React.CSSProperties['flexDirection']} [dir]
	 * @property {React.CSSProperties['flexGrow']} [grow]
	 * @property {React.CSSProperties['flexFlow']} [flow]
	 * @typedef {Object} props
	 * @property {boolean  | FlexOption} [Flex] - 
	 * @property {boolean | 'reverse' } [Column] - 
	 * @property {boolean | number } [Grow] - 
	 * @property { React.CSSProperties['position'] } [Position] - 
	 * @property {bgcolor} [ColorBg] - colors
	 * @property {boolean|number} [Fit] - number % w,h
	 * @property {boolean|React.CSSProperties['overflowX']} [OverflowX] -
	 * @property {boolean|React.CSSProperties['overflowY']} [OverflowY] -
	 * @property {number|{x:number,y:number}|[number,number,number,number]} [P] - padding: [ left, top, right, bottom ]
	 * @property {number|'auto'|{x:number,y:number}|[number,number,number,number]} [M] - margin: [ left, top, right, bottom ]
	 * @typedef {props & React.HTMLAttributes<HTMLDivElement>  } Child
	 * @param {Child} props Component props
	 */
	(
		{ Flex, Column, Grow, ColorBg, Fit, Position, P, M, OverflowX, OverflowY, children, style = {}, ...rest },
		ref,
	) => {
		if (Flex || Column) {
			style.display = style.display || 'flex';
		}
		if (Column) {
			style.flexDirection = _.isString(Column) ? 'column-reverse' : 'column';
		}
		if (Grow) {
			style.flexGrow = +Grow;
		}
		if (Position) {
			style.position = Position;
		}
		if (ColorBg) {
			style.backgroundColor = ColorBg;
		}
		if (OverflowX || OverflowY) {
			style.overflowX = _.isBoolean(OverflowX) ? 'scroll' : OverflowX;
			style.overflowY = _.isBoolean(OverflowY) ? 'scroll' : OverflowY;
		}
		if (Fit) {
			style.minWidth = '0px';
			style.minHeight = '0px';
			style.width = '100%';
			style.height = '100%';
		}
		if (P) {
			style.padding = _.isNumber(P)
				? `${P}px ${P}px ${P}px ${P}px`
				: _.isArray(P)
				? `${P[0]}px ${P[1]}px ${P[2]}px ${P[3]}px`
				: `${P.x}px ${P.x}px ${P.y}px ${P.y}px`;
		}
		if (M) {
			style.margin = _.isNumber(M)
				? `${M}px ${M}px ${M}px ${M}px`
				: _.isArray(M)
				? `${M[0]}px ${M[1]}px ${M[2]}px ${M[3]}px`
				: `${M.x}px ${M.x}px ${M.y}px ${M.y}px`;
		}
		return (
			<div ref={ref} {...rest} style={style}>
				{children}
			</div>
		);
	},
);

@Kazerian
Copy link

Yes, i have the same question. can anyone mention the usecase of forwardRef that cant be achieved by sending refs as props? there must be a reason for introducing forwardRef

Have a look at this code https://codesandbox.io/s/snowy-feather-yrsjwn?file=/src/App.js
It is a simple example of both, passing ref as props as well as using forwardRef

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment