question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Disallow excess properties to React components (for performance)

See original GitHub issue

Search Terms

react excess props properties component function parameters

Suggestion

import * as React from 'react';
import { ComponentType } from 'react';

type Props = { foo: 1 };
declare const MyComponent: ComponentType<Props>;
declare const propsWithExtras: Props & { bar: 1 };

// Expected error, but got none
<MyComponent {...propsWithExtras} />;

I understand this matches TypeScript’s behaviour with functions:

type Props = { foo: 1 };
declare const MyFunction: (props: Props) => void;
declare const propsWithExtras: Props & { bar: 1 };

// No error
MyFunction(propsWithExtras);
MyFunction({ ...propsWithExtras });

However, with React, passing excess props to a component is a performance concern, since those excess props may break component memoization, causing the component to update more frequently than it should.

In my experience, this error most often occurs when wrapping components, where the wrapper components need to “pass through” types to a child:

type MyComponentProps = { foo: 1 };
declare const MyComponent: ComponentType<MyComponentProps>;

type MyWrapperComponent = MyComponentProps & { myWrapperProp: 1 };
const MyWrapperComponent: ComponentType<MyWrapperComponent> = props => (
    <MyComponent
        // We're passing too many props here, but no error!
        {...props}
    />
);

Workarounds I’m aware of: (1) avoid spreading, but this quickly becomes a non-option when a component has many props you have to manually pick and pass through.

const MyWrapperComponent: ComponentType<MyWrapperComponent> = ({ foo, myWrapperProp }) => (
    // Error as expected due to excess prop `myWrapperProp`
    <MyComponent foo={foo} myWrapperProp={myWrapperProp} />
);

(2) Pass through props via an object.

type MyWrapperComponent = { myComponentProps: MyComponentProps } & { myWrapperProp: 1 };
const MyWrapperComponent: ComponentType<MyWrapperComponent> = ({ myComponentProps, myWrapperProp }) => (
    // Error as expected due to excess prop `myWrapperProp`
    <MyComponent {...myComponentProps} myWrapperProp={myWrapperProp} />
);

However then we lose special JSX behaviour such as the ability to pass data attributes as props.

IIUC, this could be a use case for https://github.com/Microsoft/TypeScript/issues/12936.

Checklist

My suggestion meets these guidelines:

  • This wouldn’t be a breaking change in existing TypeScript/JavaScript code
  • This wouldn’t change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn’t a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • This feature would agree with the rest of TypeScript’s Design Goals.

Issue Analytics

  • State:open
  • Created 5 years ago
  • Reactions:28
  • Comments:13 (3 by maintainers)

github_iconTop GitHub Comments

25reactions
devuxercommented, Sep 4, 2019

I find it completely baffling that…

<div garbage={3}>Garbage</div> doesn’t compile

while

<div {...{ garbage: 3 }}>Garbage</div> does compile

This violates the principle of least surprise, and honestly, I would categorize this as a bug fix, not a feature request.

That said, I don’t see why fixing this wouldn’t be a breaking change. It would turn previously compiling code into code that doesn’t compile. I would think we’d need a new tsconfig strictness setting (e.g., disallowExcessJsxAttributes).

9reactions
lwollecommented, Sep 17, 2021

Does anyone know if there is an existing lint rule somewhere that could be used to solve the pain for the time being?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Optimizing React performance by preventing unnecessary ...
Only re-rendering React components when necessary can make app your faster. This article explains how to reduce re-renders and avoid common ...
Read more >
Just Say No to Excessive Re-Rendering in React
In this article, we will address instances of excessive re-rendering in React applications and demonstrate how to avoid them.
Read more >
How to Optimize Components to Improve React Performance
In this tutorial, you will learn how to maximize React performance by measuring rendering bottlenecks and optimizing your components.
Read more >
How can one prevent excess JS event handlers in React?
addEventListener appears to occur only once, but event listeners pile up and negatively affect performance. Code. Here's the pared down source ...
Read more >
How to identify and resolve wasted renders in React
By default, React will render the virtual DOM and compare the difference for every component in the tree for any change in its...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found