Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rule proposal: detect unnecessary use of fragments #2042

Closed
moretti opened this issue Nov 12, 2018 · 12 comments · Fixed by #2261
Closed

Rule proposal: detect unnecessary use of fragments #2042

moretti opened this issue Nov 12, 2018 · 12 comments · Fixed by #2261

Comments

@moretti
Copy link

moretti commented Nov 12, 2018

The idea behind fragments is to group a list of children without adding extra nodes to the DOM.
Fragments are completely redundant when wrapping a single child, so the rule should detect examples like:

<>
  <div />
</>
<Fragment>
  <div />
</Fragment>

and flag them as a warning/error.

Example of valid usage of fragments:

<>
  <div />
  <div />
</>

(any case where children.length > 1)

@ljharb
Copy link
Member

ljharb commented Nov 12, 2018

This is a good rule (altho until enzyme supports rendering non-nodes, a fragment with a non-node child is still necessary, so perhaps that should be controllable via a separate option).

Both forms - syntax and API - should be checked.

@pawelnvk
Copy link

pawelnvk commented Apr 13, 2019

I would love to work on this one! Could you elaborate more about both options? How would look like "non-node" child? Code snippet would be helpful.

golopot added a commit to golopot/eslint-plugin-react that referenced this issue May 5, 2019
@golopot
Copy link
Contributor

golopot commented May 12, 2019

Other cases:

  1. Looks useless
const Foo = () => (
  <div>
    <>
      <div />
      <div />
    </>
  </div>
)
  1. Looks useless, but arguable.
const Goo = () => (
  <div>
    <>
      <div />
      <div />
    </>
    <section />
  </div>
)
  1. Not useless if it is a child of a non-dom component.
const Hoo = () => (
  <Moo>
    <>
      <div />
      <div />
    </>
  </Moo>
)

@ljharb
Copy link
Member

ljharb commented May 12, 2019

I do think it’s always useless to pass a fragment as a child to an html element; the rule should warn on that too.

@golopot
Copy link
Contributor

golopot commented May 12, 2019

Here comes the problem of whether a tag is a html element, also noted in #1752 (comment). Maybe in this case it is ok to maintain a list of html tags in this repo, since in #1752 an omission of an html tag name is false positive, whereas in this rule, an omission is false negative.

@ljharb
Copy link
Member

ljharb commented May 12, 2019

It’s an html element if the tag name is lowercase and doesn’t have a dot in it; that’s how jsx works - that comment is about knowing whether it’s a valid tag name or not.

@ljharb
Copy link
Member

ljharb commented May 12, 2019

I suppose the autofix for that case wouldn’t be as safe if it wasn’t a valid tag name; but we could still warn on it.

golopot added a commit to golopot/eslint-plugin-react that referenced this issue May 16, 2019
golopot added a commit to golopot/eslint-plugin-react that referenced this issue May 16, 2019
@TkDodo
Copy link

TkDodo commented Sep 27, 2019

When can we expect this to be released? It's been some time since this has been finished ...

@paolostyle
Copy link

What if I have a component that looks like this (very trivial example, usually the stuff in the map is a bit more complicated):

const Component = ({ someArray }) => {
  return (
    <>
      {someArray.map(item => <span>{item}</span>)}
    </>
  );

The rule reports an error but I think there shouldn't be one. Obviously it is possible that there will be 0, 1 or more children inside fragment, but I think there should be way to disable the rule for these situations through config.

@ljharb
Copy link
Member

ljharb commented Oct 3, 2019

@paolostyle in that case, you're already missing a key inside the array; however components in react 16 can render arrays directly, so there's no need for the fragment.

@paolostyle
Copy link

paolostyle commented Oct 3, 2019

That was just an artificial example, I always have keys in arrays in actual code because I use a linting rule for that, I don't think that's relevant here.

My whole codebase is in Typescript and I can't return an array from function components (and 95% of them are function components), there's a couple of links to Typescript and React types GH issues in this SO thread: https://stackoverflow.com/questions/46643517/return-react-16-array-elements-in-typescript.

I suppose my example is actually just a workaround so I just won't use this rule until it's fixed in TS/React types. Looking at how old this issue is I probably won't ever use it but oh well.

@ljharb
Copy link
Member

ljharb commented Oct 3, 2019

TypeScript having broken types for React is something that TS needs to fix; my suggested workaround would be to not use TS :-p (but that SO answer tells you how to patch the types so it works)

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

Successfully merging a pull request may close this issue.

6 participants