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-zustand-rules

v1.0.2

Published

An ESLint plugin for enforcing best practices in Zustand, including adherence to Flux architecture, promoting efficient state management, and avoiding anti-patterns.

Downloads

6

Readme

eslint-plugin-zustand-rules

This ESLint plugin helps enforce best practices when using Zustand for state management. It provides rules that encourage consistency, prevent common issues, and promote scalable state management patterns in large applications.

Installation

Install the plugin using npm or yarn:

npm install --save-dev eslint-plugin-zustand-rules

or

yarn add --dev eslint-plugin-zustand-rules

Usage

Add the plugin to your ESLint configuration file:

.eslintrc.json example:

{
  "plugins": ["zustand-rules"],
  "extends": ["eslint:recommended", "plugin:zustand-rules/recommended"]
}

.eslintrc.js example:

module.exports = {
  plugins: ['zustand-rules'],
  extends: ['eslint:recommended', 'plugin:zustand-rules/recommended'],
};

Rules

The plugin contains the following rules:

zustand-rules/no-multiple-stores

Ensures there is only one Zustand store per module. Zustand encourages managing the entire global state within a single store, although you can split state into slices for large applications. This rule ensures only one create call (store) is used per module.

Rule Details

This rule reports an error when more than one create function call is found in a module.

Examples

🚫 Incorrect:

// Multiple Zustand stores in a single file
const useStoreA = create((set) => ({
  bears: 0,
}));

const useStoreB = create((set) => ({
  fish: 0,
}));

Correct:

// Single Zustand store in a module
const useStore = create((set) => ({
  bears: 0,
  fish: 0,
  increasePopulation: () => set((state) => ({ bears: state.bears + 1 })),
}));

zustand-rules/use-store-selectors

Enforces the use of selectors when accessing values from Zustand stores to avoid unnecessary re-renders. This improves performance and makes the code more predictable.

Rule Details

This rule checks whether useStore is used without a selector function.

Examples

🚫 Incorrect:

// Without selector
const state = useStore();

Correct:

// With selector
const bears = useStore((state) => state.bears);

zustand-rules/no-state-mutation

Prevents direct state mutation. Always use set or setState to update the store to ensure proper reactivity.

Rule Details

This rule reports an error when direct state mutations (e.g., state.bears += 1) are detected in store actions.

Examples

🚫 Incorrect:

// Direct mutation of state
const useStore = create((set) => ({
  bears: 0,
  increment: () => {
    state.bears += 1;
  },
}));

Correct:

// Properly using set to update state
const useStore = create((set) => ({
  bears: 0,
  increment: () => set((state) => ({ bears: state.bears + 1 })),
}));

zustand-rules/enforce-use-setstate

Ensures state is updated via set or setState. This rule checks that updates to the store's state use the proper functions to ensure proper reactivity and avoid direct state mutations.

Rule Details

This rule reports an error if direct state mutations are detected and suggests using set or setState instead.

Examples

🚫 Incorrect:

// Direct state mutation
const useStore = create(() => ({
  bears: 0,
  setBears: () => {
    state.bears += 1;
  },
}));

Correct:

// Using set to update state
const useStore = create((set) => ({
  bears: 0,
  setBears: () => set((state) => ({ bears: state.bears + 1 })),
}));

zustand-rules/enforce-state-before-actions

Ensures state properties are listed before action functions. This improves the readability and structure of Zustand stores by ensuring that all state properties are defined before any action functions.

Rule Details

This rule reports an error when action functions are defined before state properties.

Examples

🚫 Incorrect:

// Action function before state property
const useStore = create((set) => ({
  increment: () => set(state => ({ bears: state.bears + 1 })),
  bears: 0,
}));

Correct:

// State property before action function
const useStore = create((set) => ({
  bears: 0,
  increment: () => set(state => ({ bears: state.bears + 1 })),
}));

zustand-rules/enforce-slices-when-large-state

Encourages creating slices if the Zustand store state gets too large. This rule checks the number of properties in the Zustand store and suggests splitting the store into slices if it contains too many properties, improving code modularity and maintainability.

Rule Details

This rule enforces the use of slices when the number of state properties exceeds a certain threshold. The default threshold is set to 5 properties, but you can customize this in your ESLint configuration.

Examples

🚫 Incorrect (Too many properties):

// Large Zustand stores make hard to organize and maintain
const useStore = create((set) => ({
  bears: 0,
  fish: 0,
  birds: 0,
  trees: 0,
  plants: 0,
  sky: 0,
  clouds: 0,
  bugs: 0,
  raccoon: 0,
  incrementBears: () => set((state) => ({ bears: state.bears + 1 })),
}));

Correct (Using slices):

// Zustand store with slices allow for better organization and thought separation
const createBearSlice = (set) => ({
  bears: 0,
  incrementBears: () => set((state) => ({ bears: state.bears + 1 })),
});

const createFishSlice = (set) => ({
  fish: 0,
  incrementFish: () => set((state) => ({ fish: state.fish + 1 })),
});

const useStore = create((set) => ({
  ...createBearSlice(set),
  ...createFishSlice(set),
}));

Recommended Configuration

You can configure the maximum number of properties allowed in a store before suggesting slices:

{
  "rules": {
    "zustand-rules/enforce-slices-when-large-state": ["warn", { "maxProperties": 10 }]
  }
}

License

This project is licensed under the MIT License - see the LICENSE file for details.