Skip to content
This repository has been archived by the owner on Jul 15, 2023. It is now read-only.

react-unused-props-and-state fails with SFC's #339

Closed
bookman25 opened this issue Jan 29, 2017 · 17 comments · Fixed by #824
Closed

react-unused-props-and-state fails with SFC's #339

bookman25 opened this issue Jan 29, 2017 · 17 comments · Fixed by #824
Labels
Difficulty: Hard Only someone with heavy experience in TSLint should be able to send a pull request for this issue. Status: Accepting PRs Type: Bug
Milestone

Comments

@bookman25
Copy link

This rule appears to only work with this.props calls. So SFC's don't work because there is no this pointer.

Also, once you destructure props/state, it assumes all keys are used. Even if you only reference some of the props in the destructure:

interface State {
  key1: string;
  key2: string;
}
...
const { key1 } = this.state;  // this will mark all keys as used
@HamletDRC
Copy link
Member

Can you post a sample of one of your SFCs?

@HamletDRC
Copy link
Member

Here is one possible syntax for SFC:

import classNames = require('classnames');
import CommonKey = require('common/locales/CommonKey');
import I18nFacade = require('common/i18n/I18nFacade');
import React = require('react');

'use strict';

const buttonLabel: string = I18nFacade.TEXT(CommonKey.close());

module XCloseButton {

    export interface Props extends React.Props<React.HTMLAttributes> {
        className?: string;
        onClick: () => void;
    }
}

/**
 * Render an 'X' styled closed button
 */
/* tslint:disable:variable‐name */
function XCloseButton({ className, onClick }: XCloseButton.Props): ReactTypes.ReactElement<any> {
/* tslint:enable:variable‐name */
    return (
        <button
            className={classNames('XCloseButton', className)}
            onClick={onClick}
            aria-label={buttonLabel}
            title={buttonLabel}
        />
    );
}

export = XCloseButton;

@narthollis
Copy link

I am also experiencing this issue, tslint output follows reproduction.

Reproduction

interface Props {
    children?: React.ReactNode;
    heading: string;

    className?: string;
}

export function TestComponent(props: Props) {
    return (
        <div className={props.className || ''}>
            <h3>{props.heading}</h3>
            {props.children}
        </div>
    )
}

export default TestComponent;

Output

src/components/TestComponent.tsx
58:6  semicolon                     Missing semicolon
46:5  react-unused-props-and-state  Unused React property defined in interface: children
47:5  react-unused-props-and-state  Unused React property defined in interface: heading
49:5  react-unused-props-and-state  Unused React property defined in interface: className

@bookman25
Copy link
Author

Sorry about the late response, just saw there was a comment. Here's an example SFC. Both properties are being flagged as unused.

tslint.json

"react-unused-props-and-state": [
	true,
	{
		"props-interface-regex": "IProps$",
		"state-interface-regex": "State$"
	}
]

SFC

interface IProps {
	test: string;
	test2: string;
}

export function Test(props: IProps) {
	return <div>{ props.test }</div>;
}

@markmcdermid
Copy link

I'm having this issue too

@kokjinsam
Copy link

Any updates on this issue?

@HamletDRC
Copy link
Member

None yet. I looked at it briefly, but a proper solution that covers all the destructuring corner cases is fairly time consuming to write. I am currently on vacation but have reserved next Monday to continue to look into this.

@j-f1
Copy link

j-f1 commented Jun 27, 2017

@HamletDRC Any news on this?

@HamletDRC
Copy link
Member

Nothing yet.

@JoshuaKGoldberg
Copy link

Ok, I just had to look this up: SFC === Stateless Functional Component. Been using them for years and didn't think of that as the abbreviation...

@JoshuaKGoldberg JoshuaKGoldberg added Type: Bug Status: Accepting PRs Difficulty: Hard Only someone with heavy experience in TSLint should be able to send a pull request for this issue. labels Jul 6, 2018
@skitterm
Copy link

Also seeing this. For some reason, this fails:

interface Props {
  children: JSX.Element | JSX.Element[];
  className: string;
}

const ButtonGroup: SFC<Props> = (props: Props) => {
  return (
    <div className={props.className}>
      {props.children}      
    </div>
  )
};

But changing Props to SomeRandomProps passes:

interface SomeRandomProps{
  children: JSX.Element | JSX.Element[];
  className: string;
}

const ButtonGroup: SFC<SomeRandomProps> = (props: SomeRandomProps) => {
  return (
    <div className={props.className}>
      {props.children}      
    </div>
  )
};

It's not ideal to have to call Props something else since it's less clear.

@agjs
Copy link

agjs commented Nov 27, 2018

The comment above is pretty frightening. Can someone elaborate on why provided works and naming stuff Props doesn't? Let's write code, not magic..

@itsMapleLeaf
Copy link

It passes probably because SomeRandomProps doesn't fall under the default pattern, which only checks for Props. It's passing because TSLint isn't verifying it at all. I haven't tested myself to be sure, so correct me if I'm wrong.

@kylegillen
Copy link

kylegillen commented Nov 30, 2018

Any progress on this? I just posted an issue referencing this exact issue almost 2 years after this was posted :(

@JoshuaKGoldberg
Copy link

@nextriot it's still accepting PRs if anybody (you? 😉) is up for contributing a solution to the issue. As HamletDRC noted, a proper solution that covers all the destructuring corner cases is fairly time consuming to write. Unless you have the time to start on it yourself, I wouldn't expect a solution to this anytime soon.

@kylegillen
Copy link

kylegillen commented Dec 3, 2018

Thanks for taking the time to reply @JoshuaKGoldberg. If I knew where (or even how) to start, I'd very much like to contribute.

Any idea what developers are doing in the meantime? Is there some hack that can be employed?

@JoshuaKGoldberg
Copy link

JoshuaKGoldberg commented Dec 3, 2018

Yeah contributing docs are something that could be a bit spruced up with TSLint (open issues) ☹... A few handy docs on getting started:

Hope this helps, and feel free to reach out on Gitter or Twitter (publicly or DMs) if you have any questions! It'd be great to have more people tackling these issues!

mattmazzola added a commit to microsoft/ConversationLearner-UI that referenced this issue Jan 30, 2019
See: microsoft/tslint-microsoft-contrib#339

Apparently when using React.SFC there are some issues. I don't understand why renaming has any effect but it works
mattmazzola added a commit to microsoft/ConversationLearner-UI that referenced this issue Jan 31, 2019
See: microsoft/tslint-microsoft-contrib#339

Apparently when using React.SFC there are some issues. I don't understand why renaming has any effect but it works
@IllusionMH IllusionMH added this to the 6.1.0-beta milestone Feb 19, 2019
mattmazzola added a commit to microsoft/conversationlearner that referenced this issue Dec 16, 2019
See: microsoft/tslint-microsoft-contrib#339

Apparently when using React.SFC there are some issues. I don't understand why renaming has any effect but it works
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Difficulty: Hard Only someone with heavy experience in TSLint should be able to send a pull request for this issue. Status: Accepting PRs Type: Bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.