# I built the simplest react state management library (usecat)

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1725025858698/d7833c0d-b70e-465f-ac5b-6f31dc3ed64d.png align="center")

There are so many state management libs for react, but they are too complex / not easy to use for me. I only need these:

* Create state for something;
    
* Update the state out of component;
    
* Get the state out of component;
    
* A hook to read state within component;
    

So I created the lib myself, it's dead simple but very flexible, I have a cat, so I call the lib usecat, [github link here](https://github.com/penghuili/usecat). It's so simple that I can list the whole source code here:

```javascript
import { useEffect, useReducer } from 'react';

const cats = [];

export function createCat(initialValue) {
  let value = initialValue;
  const listeners = new Set();

  const get = () => value;

  const set = (newValue) => {
    if (newValue !== value) {
      const oldValue = value;
      value = newValue;
      listeners.forEach((listener) => listener(oldValue, newValue));
    }
  };

  const reset = () => set(initialValue);

  const subscribe = (listener) => {
    listeners.add(listener);
    return () => listeners.delete(listener);
  };

  const cat = { get, set, reset, subscribe };
  cats.push(cat);

  return cat;
}

export function useCat(cat, selector = (value) => value) {
  const [, forceUpdate] = useReducer((x) => x + 1, 0);

  useEffect(() => {
    const handler = (oldValue, newValue) => {
      const oldSlice = selector(oldValue);
      const newSlice = selector(newValue);
      if (oldSlice !== newSlice) {
        forceUpdate();
      }
    };
    const unsubscribe = cat.subscribe(handler);
    return () => unsubscribe();
  }, [cat]);

  return selector(cat.get());
}
```

## Usage is also simple

Create some cats:

```javascript
import { createCat } from 'usecat';

const isLoadingTodosCat = createCat(false);
const todosCat = createCat([]);
```

Get and set values out of component:

```javascript
import { isLoadingTodosCat, todosCat } from './cats';

async function fetchTodos() {
  const currentTodos = todosCat.get();
  if (currentTodos?.length) {
    return;
  }

  isLoadingTodosCat.set(true);

  try {
    const response = await fetch('your-fancy-api');
    const todos = await response.json();
    todosCat.set(todos);
  } catch (e) {
    // handle error yourself ;)
  }

  isLoadingTodosCat.set(false);
}
```

Use hook to get value updates:

```javascript
import { useCat } from 'usecat';
import { isLoadingTodosCat, todosCat } from './cats'
import { fetchTodos } from './network';

function MyComponent() {
  const isLoading = useCat(isLoadingTodosCat);
  const todos = useCat(todosCat);

  useEffect(() => {
    fetchTodos();
  }, [])

  return (
     <>
        {isLoading && <div>loading ...</div>}
        {todos.map(todo => (
          <div key={todo.id}>{todo.title}</div>
        ))}
      </>
  )
}
```

I am using this simple thing to build all my projects, like [notenote.cc](https://notenote.cc?ref=blog-cat), check its [source code](https://github.com/penghuili/notenotecc), it's open.
