Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

537
Views
Using a forwardRef component with children in TypeScript

Using @types/react 16.8.2 and TypeScript 3.3.1.

I lifted this forward refs example straight from the React documentation and added a couple type parameters:

const FancyButton = React.forwardRef<HTMLButtonElement>((props, ref) => (
  <button ref={ref} className="FancyButton">
    {props.children}
  </button>
));

// You can now get a ref directly to the DOM button:
const ref = React.createRef<HTMLButtonElement>();
<FancyButton ref={ref}>Click me!</FancyButton>;

I get the following error in the last line under FancyButton:

Type '{ children: string; ref: RefObject<HTMLButtonElement>; }' is not assignable to type 'IntrinsicAttributes & RefAttributes<HTMLButtonElement>'. Property 'children' does not exist on type 'IntrinsicAttributes & RefAttributes<HTMLButtonElement>'.ts(2322)

It would seem that the type definition for React.forwardRef's return value is wrong, not merging in the children prop properly. If I make <FancyButton> self-closing, the error goes away. The lack of search results for this error leads me to believe I'm missing something obvious.

over 4 years ago · Santiago Trujillo
3 answers
Answer question

0

trevorsg, you need to pass the button properties:

import * as React from 'react'

type ButtonProps = React.HTMLProps<HTMLButtonElement>

const FancyButton = React.forwardRef<HTMLButtonElement, ButtonProps>((props, ref) => (
  <button type="button" ref={ref} className="FancyButton">
    {props.children}
  </button>
))

// You can now get a ref directly to the DOM button:
const ref = React.createRef<HTMLButtonElement>()

<FancyButton ref={ref}>Click me!</FancyButton>

ADDED:

In recent versions of TS and @types/react, you can also use React.ComponentPropsWithoutRef<'button'> instead of React.HTMLProps<HTMLButtonElement>

over 4 years ago · Santiago Trujillo Report

0

The answers given by aMarCruz and euvs both work, but they lie to consumers a little bit. They say they accept all HTMLButtonElement props, but they ignore them instead of forwarding them to the button. If you're just trying to merge in the children prop correctly, then you might want to use React.PropsWithChildren instead:

import React from 'react';

interface FancyButtonProps {
    fooBar?: string; // my custom prop
}

const FancyButton = React.forwardRef<HTMLButtonElement, React.PropsWithChildren<FancyButtonProps>>((props, ref) => (
    <button type="button" ref={ref} className="fancy-button">
        {props.children}
        {props.fooBar}
    </button>
));

FancyButton.displayName = 'FancyButton';

Or explicitly add a children prop:

interface FancyButtonProps {
    children?: React.ReactNode;
    fooBar?: string; // my custom prop
}

const FancyButton = React.forwardRef<HTMLButtonElement, FancyButtonProps>((props, ref) => (
    <button type="button" ref={ref} className="fancy-button">
        {props.children}
        {props.fooBar}
    </button>
));

FancyButton.displayName = 'FancyButton';

Or if you actually want to accept all the button props and forward them (let consumers choose button type="submit", for example), then you might want to use rest/spread:

import React from 'react';

interface FancyButtonProps extends React.ComponentPropsWithoutRef<'button'> {
    fooBar?: string; // my custom prop
}

const FancyButton = React.forwardRef<HTMLButtonElement, FancyButtonProps>(
    ({ children, className = '', fooBar, ...buttonProps }, ref) => (
        <button {...buttonProps} className={`fancy-button ${className}`} ref={ref}>
            {children}
            {fooBar}
        </button>
    ),
);

FancyButton.displayName = 'FancyButton';
over 4 years ago · Santiago Trujillo Report

0

The answer given by aMarCruz works well. However, if you also need to pass custom props to the FancyButton, here is how it can be done.

interface FancyButtonProps extends React.ComponentPropsWithoutRef<'button'> {
    fooBar?: string; // my custom prop
}

const FancyButton = React.forwardRef<HTMLButtonElement, FancyButtonProps>((props, ref) => (
    <button type="button" ref={ref} className="FancyButton">
        {props.children}
        {props.fooBar}
    </button>
));


/// Use later

// You can now get a ref directly to the DOM button:
const ref = React.createRef<HTMLButtonElement>()

<FancyButton ref={ref} fooBar="someValue">Click me!</FancyButton>

Just adding here for completion.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!