npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

eslint-plugin-immutable

v1.0.0

Published

ESLint plugin to disable all mutation in JavaScript.

Downloads

80,579

Readme

eslint-plugin-immutable

This is an ESLint plugin to disable all mutation in JavaScript. Think this is a bit too restrictive? Well if you're using Redux and React, there isn't much reason for your code to be mutating anything. Redux maintains a mutable pointer to your immutable application state, and React manages your DOM state. Your components should be stateless functions, translating data into Virtual DOM objects whenever Redux emits a new state. These ESLint rules explicitly prohibit mutation, effectively forcing you to write code very similar to Elm in React.

Installing

npm install eslint-plugin-immutable --save-dev

ESLint Rules

There are three rules in the plugin:

no-let

There's no reason to use let in a Redux/React application, because all your state is managed by either Redux or React. Use const instead, and avoid state bugs altogether.

let x = 5; // <- Unexpected let or var, use const.

What about for loops? Loops can be replaced with the Array methods like map, filter, and so on. If you find the built-in JS Array methods lacking, use lodash.

const SearchResults = 
  ({ results }) => 
    <ul>{
      results.map(result => <li>result</li>) // <- Who needs let?
    }</ul>;

no-this

Thanks to libraries like recompose and Redux's React Container components, there's not much reason to build Components using React.createClass or ES6 classes anymore. The no-this rule makes this explicit.

const Message = React.createClass({
  render: function() {
    return <div>{ this.props.message }</div>; // <- no this allowed
  }
})

Instead of creating classes, you should use React 0.14's Stateless Functional Components and save yourself some keystrokes:

const Message = ({message}) => <div>{ message }</div>;

What about lifecycle methods like shouldComponentUpdate? We can use the recompose library to apply these optimizations to your Stateless Functional Components. The recompose library relies on the fact that your Redux state is immutable to efficiently implement shouldComponentUpdate for you.

import { pure, onlyUpdateForKeys } from 'recompose';

const Message = ({message}) => <div>{ message }</div>;

// Optimized version of same component, using shallow comparison of props
// Same effect as React's PureRenderMixin
const OptimizedMessage = pure(Message);

// Even more optimized: only updates if specific prop keys have changed
const HyperOptimizedMessage = onlyUpdateForKeys(['message'], Message);

no-mutation

You might think that prohibiting the use of let and var would eliminate mutation from your JavaScript code. Wrong. Turns out that there's a pretty big loophole in const...

const point = { x: 23, y: 44 };
point.x = 99; // This is legal

This is why the no-mutation rule exists. This rule prevents you from assigning a value to the result of a member expression.

const point = { x: 23, y: 44 };
point.x = 99; // <- No object mutation allowed.

This rule is just as effective as using Object.freeze() to prevent mutations in your Redux reducers. However this rule has no run-time cost. A good alternative to object mutation is to use the object spread syntax coming in ES2016.

const point = { x: 23, y: 44 };
const transformedPoint = { ...point, x: 99 };

You can enable this syntax using the syntax-object-rest-spread Babel plug-in.

Supplementary ESLint Rules to Enable

The rules in this package alone can not eliminate mutation in your JavaScript programs. To go the distance I suggest you also enable the following built-in ESLint rules:

  • no-var (self-explanatory)
  • no-undef (prevents assigning to global variables that haven't been declared)
  • no-param-reassign (prevents assigning to variables introduced as function parameters)

Sample Configuration File

Here's a sample ESLint configuration file that activates these rules:

{
    "extends": "airbnb",
    "plugins": [
        "immutable"
    ],
    "rules": {
    	"immutable/no-let": 2,
    	"immutable/no-this": 2,
    	"immutable/no-mutation": 2
    }
}

Special Thanks to cerealbox who paired with me on this.