loading...
Cover image for Introducing Object Hooks: Mutable State for React 🤯

Introducing Object Hooks: Mutable State for React 🤯

shiftyp profile image Ryan Lynch (he/him) ・2 min read

The idea I started with is: What if we could write state changes in react as mutations on a persistent reference? 🤔 So I wrote the code to make it work! The basic concept is summed up in the code from the banner image:

import React from 'react';

import { useObject } from '../hooks/useObject';

export const Counter: React.FC = () => {
  const [state] = useObject({
    count: 1,
  });

  return (
    <button
      onClick={() => {
        state.count++;
      }}
    >
      {state.count}
    </button>
  );
};

In this case, state is a persistent reference that you can mutate (state.count++). The consequences of this change are fairly interesting. For one, you can create these objects with a class! So the above example could be rewritten as:

import React from 'react';

import { useInstance } from '../hooks/useInstance';

class Counter {
  count = 1;

  increment() {
    this.count++;
  }
}

export const Counter: React.FC = () => {
  const [counter] = useInstance(Counter);

  return (
    <button
      onClick={() => {
        counter.increment();
      }}
    >
      {counter.count}
    </button>
  );
};

Also, if you need to subscribe to to changes in the objects outside of a component function, they implement the AsyncIterable interface, so you can await their next state, or for await future states in an async function. Here's a logger class that subscribes to a counter!

class CounterLogger {
  constructor(
    private counter: Counter & AsyncIterable<Counter>
  ) {}

  log(count: number) {
    console.log(`Count is: ${count}`);
  }

  async watch() {
    this.log(this.counter.count);

    for await (const { count } of this.counter) {
      this.log(count);
    }
  }
}

There's more to it, and there will be more as the project progresses. I wanted to share what I have in its current "state" 😉 to give everyone a chance to contribute their thoughts and ideas! If you're interested, clone the repo and try it for yourself! Or leave a comment or question on this post! All are contributions, all are welcome. 🔰

Posted on by:

shiftyp profile

Ryan Lynch (he/him)

@shiftyp

I solve computer problems as a dev, human problems as a teacher

Discussion

markdown guide
 

Hey Ryan!

Someone else posted a link to the GitHub repository yesterday and I quickly took a look on it! Seems very interesting! I also had some thoughts about a resettable state and published my code :D

github.com/YannickFricke/react-res...

Feel free to leave any comments! :)

 
 

To be honest, I was inspired by your library! :)

A great library would be so inspiring and accessible that you could and would want to adapt parts of it or ideas from it for your own use. I'm happy it resonated with you, and you were able to pick up on the pattern and adapt it!

I just wanted this single part only without all the other stuff you have in your code.

KISS - Keep It Stupid Simple

Someone could argue that relying on to much dependencies makes the technical debt bigger and bigger. But this is so simple, you could even write it yourself :D

Thanks again for the idea! :)

The extra bit that bridges the diff between resettable state, and mutable state: is taking the setState function and calling it whenever properties on the object change. If that's not a feature you want though, then resettable state is a good solution!