Skip to content

Do we want to recommend the no-param-reassign eslint rule in the docs? #521

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

Closed
phryneas opened this issue Apr 24, 2020 · 22 comments
Closed

Comments

@phryneas
Copy link
Member

I just had this idea when another user tried to assign to the state function argument.
There is actually an eslint rule for that:
no-param-reassign

I'd suggest we either add that rule as a recommendation somehwere in the docs or go even one step farther and create a shareable config package .

That way we could add some more recommended rules in the future.

I'm thinking of later-on adding a self-written eslint-typescript rule that disallows assigning to anything of the type Draft or something similar.

@phryneas phryneas changed the title Do we want to recommend the no-param-reassign rule in the docs? Do we want to recommend the no-param-reassign eslint rule in the docs? Apr 24, 2020
@markerikson
Copy link
Collaborator

Pretty sure that rule also forbids mutating someParam.field = 123, which doesn't work well with Immer.

@phryneas
Copy link
Member Author

Only if you override the default configuration of { "props": false } to { "props": true }.
Over in immerjs/immer#189, mwestrate essentially recommends the rule in its default config.

@elramus
Copy link

elramus commented May 6, 2020

Long time user of redux here, new to RTK / Immer. Running into ESLint complaining that I'm reassigning state in createSlice. But this is fine though, right, because RTK is using produce under the hood? If so, how do you recommend using the no-param-reassign rule? I know you can do ignorePropertyModificationsFor, but in some cases I'd like to just completely rewrite state in the reducer, not just a property, for example if we're holding a loading on/off boolean.

const searchingSlice = createSlice({
  name: 'searching',
  initialState: false,
  reducers: {
    setStatus: (state, action: PayloadAction<boolean>) => {
      state = action.payload  // Error
    },
  },
})

@markerikson
Copy link
Collaborator

Assigning state = never does anything useful. All that does is change what the local variable state is pointing to, which is always a no-op.

If you want to return a completely new state value / replace the existing state, you need to actually return it: return action.payload.

@elramus
Copy link

elramus commented May 6, 2020

Ohhh okay, thanks much.

@phryneas
Copy link
Member Author

phryneas commented May 6, 2020

And that's exactly why I suggest recommending this eslint rule xD

@markerikson
Copy link
Collaborator

So what does it mean to "suggest" it in this case, exactly? Where would we document that info? How would we encourage people to do so?

@phryneas
Copy link
Member Author

phryneas commented May 6, 2020

Hmm, that's the question.

Maybe in the style guide, hand-in-hand with the immer and RTK recommendations, and/or in the documentation for createReducer and createSlice?

@markerikson
Copy link
Collaborator

That could work, yeah.

@StuartMorris0
Copy link

I'm interested to know what the proposed solution/information to be in the style guide would be here.

If you use the standard eslint setup and use an example from RTK such as:

const issuesDisplaySlice = createSlice({
  name: 'issuesDisplay',
  initialState,
  reducers: {
    displayRepo(state, action: PayloadAction<CurrentRepo>) {
      const { org, repo } = action.payload
      state.org = org                                     // <-- Error
      state.repo = repo                                 // <-- Error
    },

You would get the reassignment errors on the state. lines. What is the proposed solution here? Thanks

@phryneas
Copy link
Member Author

phryneas commented Jun 9, 2020

@StuartMorris0 that is most definitely not the standard eslint setup, as the props option to that rule defaults to false.
Are you extending some overly restrictive eslint config like the airbnb config? (Which in my personal opinion has outlived it's usefulness and is not a good default).

A correct configuration would be just no-param-reassign: "error" or no-param-reassign: ["error", { "props": false }] (which is equalivalent)

@StuartMorris0
Copy link

StuartMorris0 commented Jun 9, 2020

You're right it is the airbnb extends causing the issue, I have reverted the rule to its default.
"no-param-reassign": ["error", { "props": false }]

Thanks

@markerikson
Copy link
Collaborator

Airbnb has outlived its usefulness and is not a good default

Yes, this, 💯 :)

@StuartMorris0
Copy link

Does anyone know of any other good defaults I could review please?

@markerikson
Copy link
Collaborator

@StuartMorris0 I would start with https://www.npmjs.com/package/eslint-config-react-app .

@BenjiTheC
Copy link

Airbnb has outlived its usefulness and is not a good default

Yes, this, 💯 :)

If Airbnb rule set has outlived its usefulness, is there a newly recommended one? Thx!

@phryneas
Copy link
Member Author

phryneas commented Nov 15, 2020

@BenjiTheC what about the defaults that ship with eslint?
Or the one linked directly above your question.

@ackalhan
Copy link

ackalhan commented Dec 30, 2020

What I normally do is

  • All my reducers are in a single directory called reducers.
  • Then I want to force the eslint to disable no-param-reassign for the reducers directory only.
  • Then I create a new eslint config file(.eslintrc.json) inside the reducers directory, and add "no-param-reassign": ["error", { "props": false }] to it.

so the .eslintrc.json inside reducers directory is like below

{
  "rules": {
    "no-param-reassign": ["error", { "props": false }]
  }
}

@markerikson
Copy link
Collaborator

Now covered in our docs:

https://redux-toolkit.js.org/usage/immer-reducers#linting-state-mutations

@stevedeighton
Copy link

l'm a bit late to the party but I create my slices with naming convention of x.slice.ts, then use an override to only apply this rule to slices:

{ "files": ["src/**/*.slice.ts"], "rules": { "no-param-reassign": "off" } }

@Luk-z
Copy link
Contributor

Luk-z commented Oct 13, 2022

l'm a bit late to the party but I create my slices with naming convention of x.slice.ts, then use an override to only apply this rule to slices:

{ "files": ["src/**/*.slice.ts"], "rules": { "no-param-reassign": "off" } }

better solution, update the docs with this logic ?

@MikelArnaiz
Copy link

l'm a bit late to the party but I create my slices with naming convention of x.slice.ts, then use an override to only apply this rule to slices:

{ "files": ["src/**/*.slice.ts"], "rules": { "no-param-reassign": "off" } }

You should probably not turn off the rule completely, otherwise it won't warn you when reassigning state. What I have is:

// @filename .eslintrc.js
module.exports = {
  ...
  overrides: [
      {
        files: ['scr/**/slice.ts'],
        rules: { 'no-param-reassign': ['error', { props: false }] },
      },
    ],
}

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

No branches or pull requests

9 participants