Eslint-plugin-react: New rule: Enforce import namespace `import * as React` style

Created on 22 Apr 2020  Â·  24Comments  Â·  Source: yannickcr/eslint-plugin-react

It is recommended to use the namespace style imports when importing react. It would be good to have a rule to enforce this.

new rule question

Most helpful comment

I will not support any rule that causes more usage of import * as, which should almost never be used.

why not? it's valid javascript. people here have taken the time to give specific examples of why they prefer the import * as syntax. i think it's overly dismissive to just say no with what seems like a "because i said so" response. is this project not community driven?

while not related and quite old, the post's conclusion seems reasonable in certain cases: https://www.exratione.com/2015/12/es6-use-of-import-property-from-module-is-not-a-great-plan/

I don't think code should be altered to cater to a webpack bug/quirk.

as i'm sure you know, webpack is the default bundler in create-react-app and its usage far outweighs any other bundler: https://2019.stateofjs.com/other-tools/#build_tools

while it may contain quirks and other things you personally don't agree with, the community uses it profusely and having an _option_ to cater to it seems like it would be beneficial.

also, the person recommending this syntax isn't some random person. it's the official way React is imported internally within the React codebase. see: https://github.com/facebook/react/pull/18102

All 24 comments

That one person tweeted something does not constitute a recommendation; I strongly disagree that "webpack does something silly" is a good reason to write terrible code. import * as should only ever be used for metaprogramming - the other use case is laziness, which should be avoided. Neither applies here.

@ljharb "Enforce" is too much strong request in my opinion, sounds more polite. But I would love to have optional rule with auto-fix, and also auto-fix the case if there is destructuring occurs:

import React, { useState } from 'react'

and later in same file:

  const [on, setOn] = useState(false)

should be auto-fixed to

import * as React from 'react'

and later in same file:

  const [on, setOn] = React.useState(false)

I just prefer this kind of style. If this is not correct repository to post my idea, please point me in right direction.

I will not support any rule that causes more usage of import * as, which should almost never be used. If it's your preference, you're welcome to create your own eslint plugin and rule.

@ljharb read this https://twitter.com/sebmarkbage/status/1250284377138802689?s=21

The ugliness of code is very opinionated term, but correctness should prevail.

I've tested my codebase with "esModuleInterop": true and "allowSyntheticDefaultImports": true enabled, and there is import issues, for example with very popular library uniqueid

Also it requires to change some dynamic import()'s to Promise or async form to extract default then importing json files with "resolveJsonModule": true enabled, instead of correct

const json = import('./relative/path/to/file.json')

we have to do something like

const json = import('./relative/path/to/file.json').then(file => file.default).catch(err => console.error(err))

I've read it; I don't think he's correct, and I don't think code should be altered to cater to a webpack bug/quirk.

const json = import('./relative/path/to/file.json').then(file => file.default).catch(err => console.error(err))

The above is in fact correct, and is what the spec requires. Your code is not valid javascript if you're not doing that.

I will not support any rule that causes more usage of import * as, which should almost never be used.

why not? it's valid javascript. people here have taken the time to give specific examples of why they prefer the import * as syntax. i think it's overly dismissive to just say no with what seems like a "because i said so" response. is this project not community driven?

while not related and quite old, the post's conclusion seems reasonable in certain cases: https://www.exratione.com/2015/12/es6-use-of-import-property-from-module-is-not-a-great-plan/

I don't think code should be altered to cater to a webpack bug/quirk.

as i'm sure you know, webpack is the default bundler in create-react-app and its usage far outweighs any other bundler: https://2019.stateofjs.com/other-tools/#build_tools

while it may contain quirks and other things you personally don't agree with, the community uses it profusely and having an _option_ to cater to it seems like it would be beneficial.

also, the person recommending this syntax isn't some random person. it's the official way React is imported internally within the React codebase. see: https://github.com/facebook/react/pull/18102

please reconsider and reopen an issue

@ljharb given that in a future version of React, support for the default import won't be supported, can we consider a rule that will disallow importing the default export? i think this will be beneficial to teams now that are starting to migrate to this new pattern.

Wow, I almost forgot about this issue existence. Doing this manually is very annoying.

@rygine when that happens, you won’t need a linter rule to enforce it - your imports just won’t work.

Separately, you can named-import all the things you want; you should still never be using import *.

@rygine when that happens, you won’t need a linter rule to enforce it - your imports just won’t work.

This strategy doesn't work for large organizations. We need a way to gradually migrate our imports before making the switch. A linting rule is perfect for this.

Separately, you can named-import all the things you want; you should still never be using import *.

I'm not sure I follow. Can you explain this? The only thing we import * is React.

now:
import { Component, useState, etc }, React from ‘react’
later:
import { Component, useState, etc } from ‘react’

When you’re using the new transform, you’d just disable the react/jsx-uses-react rule, and the default import would become unused.

now:
import { Component, useState, etc }, React from ‘react’
later:
import { Component, useState, etc } from ‘react’

When you’re using the new transform, you’d just disable the react/jsx-uses-react rule, and the default import would become unused.

Oh, I thought you were referring to a rule from another plugin. Unfortunately, without enforcement of this with a rule, it won't be possible to enforce this in a larger organization.

It's already enforced inside many large corporations, for years now. You can ban import * with import/namespace, and ban React.Component and friends with no-restricted-properties. This will force the "now" style I described.

react/jsx-uses-react would be enabled when you're using the original jsx transform, and disabled when you're using the new one, and you'd use the core no-unused-vars rule to prevent import React when it wasn't otherwise referenced (by jsx, in this case).

There is a good article about that by @kentcdodds: Importing React Through the Ages.
The namespace is more sustainable to refactoring.

@vasilii-kovalev that claim is incorrect, although it's a very pretty webpage.

@ljharb you say that like it's objective 🤨

@kentcdodds to be clear, your article doesn't seem to be making any objective claims - i'm saying that the claim "The namespace is more sustainable to refactoring." is objectively incorrect. One can certainly use whatever one prefers, and individuals might subjectively find some approaches allow refactoring more easily than others - but that's not universal.

@ljharb it is true that `import * as React from 'react' is not universal, but currently there is a lot of inconsistencies cos there is no universal way to import react. For example in Typescript, which will prevail in upcoming years.

I'm on the side of @kentcdodds, he has all the same arguments I had, then I first posted in this issue. Typescript is very objective issue in my reality, especially imports in dependencies of dependencies, etc.

Again, I'm not saying that the rule should be enforced, just should be available to opt in, and use with --fix if enabled.

@JustFly1984 with a typescript project created within the last few years, with tsc init setting synthetic import and esModuleInterop, TS should be no different than babel - projects without these settings enabled in their tsconfig are legacy and should be modernized.

@ljharb Sorry, but not all projects could be modernized. There is a thing called backwards compatibility, that is why you can turn off any of typescript settings. There is a lot of corner cases, and import * as solves all of them for consumer apps as well as for libraries which consumer apps depends on.

@ljharb You can't expect all the authors of libraries published to npm to know all the intricacies of import/export javascript patterns for the years and all standards, and providing some universal automated way to handle import/export should be provided by tooling, the same way as semicolons and indentation is handled by eslint/prettify, instead of spending developer years to update projects manually.

@yannickcr can you please make your statement about this issue?

@JustFly1984 I think the number of published javascript libraries that use legacy TS settings, and truly can't be migrated, is quite small. If you have one, I'll be happy to make a PR to as many reasonably-used libraries as you need to migrate them; it's an embarrassingly trivial task.

Was this page helpful?
0 / 5 - 0 ratings