eslint-plugin-perfectionist
eslint-plugin-perfectionist copied to clipboard
Feature: trying to enforce a specific order within custom groups leads to complicated config
What rule do you want to change?
sort-classes
Describe the problem
I'm using perfectionist/sort-classes as a replacement for react/sort-comp which is autofixable, but I'm also trying to follow Airbnb's class order, which leads to a very verbose config for the rule...
Code example
{
type: 'natural',
ignoreCase: false,
groups: [
'static-property',
'static-method',
'property',
// React properties
'displayName',
'propTypes',
'contextTypes',
'childContextTypes',
'mixins',
'statics',
'defaultProps',
'constructor',
// React lifecycle methods
'getDefaultProps',
'getInitialState',
'state',
'getChildContext',
'getDerivedStateFromProps',
'componentWillMount',
'UNSAFE_componentWillMount',
'componentDidMount',
'componentWillReceiveProps',
'UNSAFE_componentWillReceiveProps',
'shouldComponentUpdate',
'componentWillUpdate',
'UNSAFE_componentWillUpdate',
'getSnapshotBeforeUpdate',
'componentDidUpdate',
'componentDidCatch',
'componentWillUnmount',
'handlers',
'callbacks',
['get-method', 'set-method'],
'get-set-methods',
'method',
'unknown',
'render-methods',
'main-render',
],
customGroups: [
// React properties.
{
groupName: 'displayName',
elementNamePattern: 'displayName',
},
{
groupName: 'propTypes',
elementNamePattern: 'propTypes',
},
{
groupName: 'contextTypes',
elementNamePattern: 'contextTypes',
},
{
groupName: 'childContextTypes',
elementNamePattern: 'childContextTypes',
},
{
groupName: 'mixins',
elementNamePattern: 'mixins',
},
{
groupName: 'statics',
elementNamePattern: 'statics',
},
{
groupName: 'defaultProps',
elementNamePattern: 'defaultProps',
},
// React lifecycle methods.
{
groupName: 'getDefaultProps',
elementNamePattern: 'getDefaultProps',
},
{
groupName: 'getInitialState',
elementNamePattern: 'getInitialState',
},
{
groupName: 'state',
elementNamePattern: 'state',
},
{
groupName: 'getChildContext',
elementNamePattern: 'getChildContext',
},
{
groupName: 'getDerivedStateFromProps',
elementNamePattern: 'getDerivedStateFromProps',
},
{
groupName: 'componentWillMount',
elementNamePattern: 'componentWillMount',
},
{
groupName: 'UNSAFE_componentWillMount',
elementNamePattern: 'UNSAFE_componentWillMount',
},
{
groupName: 'componentDidMount',
elementNamePattern: 'componentDidMount',
},
{
groupName: 'componentWillReceiveProps',
elementNamePattern: 'componentWillReceiveProps',
},
{
groupName: 'UNSAFE_componentWillReceiveProps',
elementNamePattern: 'UNSAFE_componentWillReceiveProps',
},
{
groupName: 'shouldComponentUpdate',
elementNamePattern: 'shouldComponentUpdate',
},
{
groupName: 'componentWillUpdate',
elementNamePattern: 'componentWillUpdate',
},
{
groupName: 'UNSAFE_componentWillUpdate',
elementNamePattern: 'UNSAFE_componentWillUpdate',
},
{
groupName: 'getSnapshotBeforeUpdate',
elementNamePattern: 'getSnapshotBeforeUpdate',
},
{
groupName: 'componentDidUpdate',
elementNamePattern: 'componentDidUpdate',
},
{
groupName: 'componentDidCatch',
elementNamePattern: 'componentDidCatch',
},
{
groupName: 'componentWillUnmount',
elementNamePattern: 'componentWillUnmount',
},
{
groupName: 'handlers',
elementNamePattern: /^handle.+$/.source,
},
{
groupName: 'callbacks',
elementNamePattern: /^on.+$/.source,
},
{
groupName: 'get-set-methods',
elementNamePattern:
/^(get|set)(?!(InitialState$|DefaultProps$|ChildContext$)).+$/
.source,
},
// Separate groups so that the main `render` comes last.
{
groupName: 'render-methods',
elementNamePattern: /^render.+$/.source,
},
{
groupName: 'main-render',
elementNamePattern: 'render',
},
],
},
Additional comments
Is there any way to configure a specific order within custom groups that I'm missing?
Validations
- [X] Read the docs.
- [X] Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
Hi @stormwarning
Could you please give a code example including:
- The initial state or currently sorted state.
- What you expect to happen instead.
This will help us better understand what feature you are looking for.
Oh, the config I'm using works, it's just not ideal for this case.
Ideally, I could define a single react-lifecycle custom group and define the exact order within it; something like
{
groupName: 'react-lifecycle',
elements: [
'componentWillMount',
'componentDidMount',
// etc...
],
}
Where elements (or what have you) is a list of patterns. Items matching would be in this group and the order of the group would be the order of the elements array itself.
Class components aren't used as much in React these days, so I understand if this isn't something to work on right away, I just wanted to point it out and see if there was a better way to configure this that I've missed
@hugop95, I think https://github.com/azat-io/eslint-plugin-perfectionist/issues/408#issuecomment-2514187578 would address the need
@OlivierZal @stormwarning
I'm actually not sure if this falls under the same need as what we discussed in #408: if I understand correctly:
- The config works and sorts with the expected order.
- But it's verbose.
Ideally, I could define a single react-lifecycle custom group and define the exact order within it
What is the objective behind this? Let's consider that you have
{
groupName: 'react-lifecycle',
elements: [
"componentWillMount",
"componentDidMount",
// etc...
],
}
and
{
groupName: 'other-stuff',
elements: [
"otherStuff1",
"otherStuff2",
// etc...
],
}
I assume you would want your groups to look like
groups: [
"react-lifecycle",
"other-stuff"
]
Is this better than doing
groups: [
"componentWillMount",
"componentDidMount",
"otherStuff1",
"otherStuff2",
]
?
Can you confirm that this is solely for convenience (and not a missing feature) purpose?
elements(or what have you) is a list of patterns. Items matching would be in this group and the order of the group would be the order of the elements array itself.
This is regrouping two things in one:
- The order of groups (the order of the
elementsarray). - What each group matches (each
elementsmember).
I see two potential issues:
- It's opinionated: choosing to match by element pattern is common, but is only one of all the filters that are offered.
customGroupsorder matters: the first custom group that matches is the one that will be used. Following your architecture, the following configuration can not explicitly tell where some elements would go:
[
"component",
"comp.*",
"com.*",
]
Where should component go? (it matches the 3 members of the array).
The current configuration system already supports this use case with the verbose config shown in the original post. While the proposed enhancement would be more convenient, it introduces architectural complexity with pattern conflicts and mixed responsibilities.
Given that class components are less commonly used today and there's a working solution available, closing this as the existing functionality covers the need.